如何检查给定的常规文件 path 是否f
是目录 path 的后代d
。如果不是符号链接,我只会检查d
(带有尾部斜杠) 是否是 的前缀f
。现在有了符号链接,这变得稍微复杂一些,因为我可以找到 祖先的物理路径,f
并将它们中的每一个与 的物理路径进行比较d
。但是,我相信可能有一个用户空间实用程序可以做到这一点,有吗?
答案1
如果文件的祖先被定义为包含该文件的目录和该目录的祖先,即目录的后代是其条目和(对于目录的条目)它们自己的后代:
假设这
$f
是常规文件的路径(而不是符号链接的路径),您可以使用 找到包含它的“真实”目录。同样,使用$(cd -- "$(dirname "$f")" && command -p pwd)
找到目录的“真实”位置。在 bash/ksh/zsh 中,您可以用替换。$d
$(cd -- "$d" && command -p pwd)
command -p pwd
pwd -P
如果
$f
是符号链接,那就比较复杂了。有些系统有readlink
命令,例如,你可以使用$(dirname "$(readlink -f -- "$f"))
较新的 GNU coreutils,但请注意,其他系统有不兼容的readlink
命令或根本没有命令。请注意,文件可能会在您进行检查和使用结果之间移动。还存在一些极端情况,问题没有明确的是/否答案,例如当从目录到文件的路径穿过挂载点时。
如果您只想知道文件系统
$f
是什么,请运行df "$f"
。如果目录的后代
$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。