【问题标题】:How can I tell if a file is a descendant of a given directory?如何判断文件是否是给定目录的后代?
【发布时间】:2020-07-02 16:18:27
【问题描述】:

从表面上看,这很简单,我可以自己轻松实现。只需依次调用 dirname() 即可上移文件路径中的每一级并检查每一级以查看它是否是我们正在检查的目录。

但是符号链接会使整个事情陷入混乱。沿被检查文件或目录路径的任何目录都可以是符号链接,并且任何符号链接都可以具有指向其他符号链接的任意符号链接链。在这一点上,我的大脑融化了,我不知道该怎么办。我已经尝试编写代码来处理这些特殊情况,但它很快就变得太复杂了,我认为我做错了。有没有一种相当优雅的方式来做到这一点?

我正在使用 Python,所以任何提及执行此操作的库都会很酷。否则,这是一个与语言无关的问题。

【问题讨论】:

    标签: python filesystems


    【解决方案1】:

    使用os.path.realpathos.path.commonprefix

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

    os.path.realpath 将扩展任何符号链接以及文件名中的..os.path.commonprefix 有点反复无常——它并没有真正测试路径,只是简单的字符串前缀,所以你应该确保你的目录以目录分隔符结尾。如果你不这样做,它会声称/the/dirtwo/filename也在/the/dir

    【讨论】:

    • 也许边缘情况都在我的脑海中。我可以发誓,在某些情况下,符号链接会使这种方法失败,但我无法举出例子来证明这一点。我觉得我在和鬼打架……
    • 因为我能想到的每个分层文件系统都需要一个唯一的、规范的、真实命名的目录,这确实有效。虽然从这里到那里可能有悖常理,但对于目录来说,“一个真正的父级”必须是真的,否则就会发生坏事。
    • 嗯,听到这个消息是个好消息。现在我只需要检查四种情况(目录和文件的真实路径和非真实路径)。谢谢!
    【解决方案2】:

    Python 3.5 有有用的函数os.path.commonpath

    返回序列路径中每个路径名的最长公共子路径。如果路径同时包含绝对路径名和相对路径名,或者路径为空,则引发 ValueError。与commonprefix() 不同,它返回一个有效路径。

    所以要检查一个文件是否是一个目录的后代,你可以这样做:

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

    commonprefix 不同,您无需担心输入是否有斜杠。 commonprefix 的返回值始终缺少尾部斜杠。

    【讨论】:

      【解决方案3】:

      在 Python 3 中执行此操作的另一种方法是使用 pathlib:

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

      请参阅 Path.resolve()Path.parents 的文档。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-13
        • 1970-01-01
        • 1970-01-01
        • 2014-04-12
        • 2017-01-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多