shell 实用程序检查目录是否是文件的祖先

shell 实用程序检查目录是否是文件的祖先

如何检查给定的常规文件 path 是否f是目录 path 的后代d。如果不是符号链接,我只会检查d(带有尾部斜杠) 是否是 的前缀f。现在有了符号链接,这变得稍微复杂一些,因为我可以找到 祖先的物理路径,f并将它们中的每一个与 的物理路径进行比较d。但是,我相信可能有一个用户空间实用程序可以做到这一点,有吗?

答案1

  1. 如果文件的祖先被定义为包含该文件的目录和该目录的祖先,即目录的后代是其条目和(对于目录的条目)它们自己的后代:

    假设这$f是常规文件的路径(而不是符号链接的路径),您可以使用 找到包含它的“真实”目录。同样,使用$(cd -- "$(dirname "$f")" && command -p pwd)找到目录的“真实”位置。在 bash/ksh/zsh 中,您可以用替换。$d$(cd -- "$d" && command -p pwd)command -p pwdpwd -P

    如果$f是符号链接,那就比较复杂了。有些系统有readlink命令,例如,你可以使用$(dirname "$(readlink -f -- "$f"))较新的 GNU coreutils,但请注意,其他系统有不兼容的readlink命令或根本没有命令。

    请注意,文件可能会在您进行检查和使用结果之间移动。还存在一些极端情况,问题没有明确的是/否答案,例如当从目录到文件的路径穿过挂载点时。

    如果您只想知道文件系统$f是什么,请运行df "$f"

  2. 如果目录的后代$d被定义为可以赋予以下形式名称的文件,$d/x1/x2/.../xn其中可以是目录或符号链接:xi

    测试此属性需要遍历以 为根的整个目录树$d,并跟踪所有符号链接。以下命令应执行此操作(警告,直接输入到浏览器中;需要 GNU find):

    [ -n "$(find -L "$d" -samefile "$f" -print -quit)" ]
    

    如果$f有硬链接,则可以通过不同的名称访问文件$f。如果您需要在名称下找到文件$f,则情况会变得更加复杂;这里有一个尝试(再次直接输入到浏览器中;需要 GNU find 和 GNU grep;假设文件名中没有换行符):

    f_directory="$(cd -- "$(dirname "$f")" && command -p pwd)"
    f_truename="$f_directory/$(basename "$f")"
    [ -n "$(find -L "$(cd "$d" && command -p pwd)" -exec readlink -f \; |
            grep -F -q -x "$f_truename")" ]
    

    无论您选择什么样的确切定义,这个属性都不是很强大,因为您可以通过添加或删除深层的符号链接来更改其值$d

答案2

我的“ls”命令有标志“--dereference-command-line-symlink-to-dir”,可显示文件的完整路径。此“ls”来自 GNU coreutils 6.9。

相关内容