我周围散落着大量像这样的链式符号链接:
A(符号链接)-> B(符号链接)-> C(文件)
有些甚至可能涉及更长的链,但我还不确定。
当手动检查单个文件时,很容易看到发生了什么,但我正在寻找一种自动化的方法来找到这些文件并(最好)清理它们。
在上面的例子中,我希望 B->C 符号链接保持不变,但 A->B 符号链接将变为 A->C
识别它们是主要目标;数量可能最终足够少,因此手动修复它们并不是什么大问题。但手动找到它们并不可行。
我知道“符号链接”实用程序,它在许多情况下都很有用,例如查找悬空的符号链接,但它似乎没有能力检测这样的“链”
我知道“find -type l”以及 find 的 -L 选项,但它们似乎不能一起工作,因为“find -L -type l”总是返回空响应。
我使用“find -type l -exec ls -l {} +”(效果比 find 的 -ls 选项更好)并尝试使用它来获取符号链接目标列表,然后我可以检查它们是否是符号链接,但是,所有符号链接都是相对的而不是绝对的,因此输出有点混乱
例如我得到如下输出:
lrwxrwxrwx 1 username 50 Nov 5 01:00 ./a/b/c/d -> ../../e/f/g/h
从那以后,我不得不想一想,才能弄清楚实际的符号链接目标是 ./a/e/f/g/h(然后我可以检查它是否是符号链接),这对于自动化来说并不理想
如果符号链接(暂时)是绝对的而不是相对的,这会更容易,但“符号链接”实用程序只能将绝对转换为相对;据我所知,它不能将相对转换为绝对。
答案1
跟踪整个链接链
真实路径
真实路径(1)为您提供链接的绝对目的地。但它只为您提供最终的目的地,所以如果您有一个链接链,它只会显示该链最终指向的最后一个真实文件/文件夹的路径。
因此,对于您的情况,如果../../e/f/g/h
是真实文件或文件夹,您将看到绝对路径。但如果其中一个组件也是符号链接,它将继续递归,直到解析途中的所有符号链接。
阅读链接
您还可以使用readlink(1)
带有 -f 或 -e 标志的命令,这将为您提供类似的结果realpath
。
-f, --canonicalize canonicalize by following every symlink in
every component of the given name recursively;
all but the last component must exist
-e, --canonicalize-existing canonicalize by following every symlink in
every component of the given name recursively,
all components must exist
避免遵循整个链接链
如果我理解正确的话,您不想跟踪到最后一个组件,而只想获取实际链接的绝对路径。这有点丑陋,但您可以执行以下操作:
LINK=./a/b/c/d
/usr/bin/realpath --no-symlinks "$(dirname ${LINK})/$(readlink ${LINK})"
解释:
$ dirname $LINK # dirname ./a/b/c/d
./a/b/c
$ readlink $LINK # readlink ./a/b/c/d
../../e/f/g/h
$ echo "$(dirname ${LINK})/$(readlink ${LINK})"
./a/b/c/../../e/f/g/h
$ /usr/bin/realpath --no-symlinks "$(dirname ${LINK})/$(readlink ${LINK})"
/home/a/e/f/g/h
如果您只想查看相对于 CWD 的链接,您可以添加 --relative-to 参数:
$ /usr/bin/realpath --no-symlinks --relative-to ./ "$(dirname ${LINK})/$(readlink ${LINK})"
a/e/f/g/h
使用 find
您可以使用 find 命令获取我之前展示的 realpath 命令的参数:
$ find ./ -type l -printf "%h/%l\n"
./a/b/c/../../e/f/g/h
从 man 中查找:
%h Leading directories of file's name (all but the last element). If
the file name contains no slashes (since it is in the current
directory) the %h specifier expands to ".".
%l Object of symbolic link (empty string if file is not a symbolic link).
然后您可以将它与上面的 realpath 命令结合起来。
$ find ./ -type l -printf "%h/%l\n" | xargs /usr/bin/realpath -s
/home/a/e/f/g/h
如果您只想查看与您的 CWD 相关的链接:
$ find ./ -type l -printf "%h/%l\n" | xargs /usr/bin/realpath -s --relative-to ./
a/e/f/g/h