如何判断文件是否为指定目录的后代?
从表面上看,这个问题挺简单的,我自己也能轻松实现。只需要一个一个地调用dirname(),逐层向上检查文件路径中的每个目录,看看是不是我们要查找的那个目录。
但是,符号链接(symlink)让事情变得复杂。路径中的任何一个目录,或者正在检查的文件的目录,都可能是一个符号链接,而任何符号链接又可以指向其他符号链接,形成任意的链接链。到这个时候,我的脑袋就有点懵了,不知道该怎么办。我尝试写代码来处理这些特殊情况,但很快就变得太复杂了,我觉得自己可能做错了。有没有什么比较优雅的方法来解决这个问题呢?
我在用Python,所以如果有哪个库可以处理这个问题,那就太好了。否则,这个问题在不同的编程语言中都是比较通用的。
3 个回答
在Python 3中,还有另一种方法可以做到这一点,就是使用pathlib
这个库:
from pathlib import Path
is_descendant = Path("/the/dir") in Path(filename).resolve().parents
你可以查看Path.resolve()
和Path.parents
的文档了解更多信息。
Python 3.5 有一个很实用的功能,叫做 os.path.commonpath
:
这个功能会返回一组路径中,最长的公共子路径。如果路径中同时包含绝对路径和相对路径,或者路径列表是空的,它会报错。跟
commonprefix()
不同的是,这个功能返回的是一个有效的路径。
所以,如果你想检查一个文件是否在某个目录下,你可以这样做:
os.path.commonpath(["/the/dir", os.path.realpath(filename)]) == "/the/dir"
与 commonprefix
不同的是,你不需要担心输入的路径后面有没有斜杠。使用 commonprefix
时,返回的结果总是没有斜杠的。
使用 os.path.realpath
和 os.path.commonprefix
:
os.path.commonprefix(['/the/dir/', os.path.realpath(filename)]) == "/the/dir/"
os.path.realpath
可以把任何符号链接和文件名中的 ..
展开成真实的路径。而 os.path.commonprefix
有点不靠谱——它其实并不是在检查路径,而只是比较字符串的前缀,所以你需要确保你的目录后面有一个目录分隔符。如果没有,它会错误地认为 /the/dirtwo/filename
也在 /the/dir
里面。