开发者

How can I tell if a file is a descendant of a given directory?

On the surface, this is pretty simple, and I could implement it myself easily. Just successively call dirname() to go up each level in the file's path and check each one to see if it's the directory we're checking for.

But symlinks throw the whole thing into chaos. Any directory along the path of either the file or directory being checked could be a symlin开发者_Python百科k, and any symlink could have an arbitrary chain of symlinks to other symlinks. At this point my brain melts and I'm not sure what to do. I've tried writing the code to handle these special cases, but it soon gets too complicated and I assume I'm doing it wrong. Is there a reasonably elegant way to do this?

I'm using Python, so any mention of a library that does this would be cool. Otherwise, this is a pretty language-neutral problem.


Use os.path.realpath and os.path.commonprefix:

os.path.commonprefix(['/the/dir/', os.path.realpath(filename)]) == "/the/dir/"

os.path.realpath will expand any symlinks as well as .. in the filename. os.path.commonprefix is a bit fickle -- it doesn't really test for paths, just plain string prefixes, so you should make sure your directory ends in a directory separator. If you don't, it will claim /the/dirtwo/filename is also in /the/dir


Python 3.5 has the useful function os.path.commonpath:

Return the longest common sub-path of each pathname in the sequence paths. Raise ValueError if paths contains both absolute and relative pathnames, or if paths is empty. Unlike commonprefix(), this returns a valid path.

So to check if a file is a descendant of a directory, you could do this:

os.path.commonpath(["/the/dir", os.path.realpath(filename)]) == "/the/dir"

Unlike commonprefix, you don't need to worry if the inputs have trailing slashes or not. The return value of commonprefix always lacks a trailing slash.


Another way to do this in Python 3 is to use pathlib:

from pathlib import Path

is_descendant = Path("/the/dir") in Path(filename).resolve().parents

See documentation for Path.resolve() and Path.parents.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜