我在一个目录中有大约 43996 个符号链接,并且想要检查它们中的任何一个在其路径的任何点是否在 posix shell 脚本中退出该目录,即使最终目标位于目录内。
例如假设以下结构:
dir/.
dir/file
dir/link -> ../dir/file
这里dir/link
最终到达一个文件dir
但是退出目录到达那里这就是我想要检测的。
我本来会打印链接位置的完整路径并附加链接内容,使用 tr 剪切符号链接的各个部分并将其传送到一段时间的读取循环以某种方式解析它,但这听起来太慢了。我希望能够在几秒钟内对所有 43996 个链接运行此操作。
我想我可以编写一个 C 程序并将上述文本通过管道传输到前面,tr
但如果可能的话,我更愿意将其保留在 POSIX shell 和实用程序中。
你能想到更好的办法吗?
这不是一件容易的事,因为您所使用的基本工具要么功能太少,要么功能太多。
readlink
只是工作的一小部分:如果指向并且它本身是符号链接,那么目标的确切位置决定了该链接是否可以接受。..
dir/link
sub/../foo
sub
sub
但是,使用常用工具,您可以创建目录树的重新定位视图,这解决了大部分问题。(这是 frostschutz 在评论中提出的建议。 )您可以使用绑定挂载创建目录树视图,并且可以使用bindfs创建绑定挂载,而无需 root 权限。您只需要使用 FUSE 的权限。
以下代码设置
$view
为显示与 相同的内容/path/to/dir
,但位于不同的位置。顶层的名称是随机生成的,并且具有在宇宙的一生中都不会发生的概率,以前曾被写下来过,因此您可以确信没有符号链接将该目录的名称作为子字符串。任何从 下开始并逃离的符号链
$view
都将无法返回到 下,因为它不包含 的顶层目录的名称$view
。因此,当且仅当在 下查看时$view
,其完全解析的目标仍在 下,符号链接才是可接受的$view
。完全解析的目标是指在展开所有符号链接之后 — 这是除断开的链接之外的链接的最终目的地。对于未断开的链接,您可以检查目标是否在 bindfs 文件系统内。使用 POSIX shell 工具,使用
df -P
并检查第二行的第一列是否包含$view
。使用 POSIX 系统调用,检查st_dev
字段是否包含与其本身相同的值。如果您的系统有它,$view
您也可以使用来检查。stat(1)
对于断开的链接,POSIX 没有帮助。GNU 和 BSD 有一个
readlink
实用程序,可以打印带有 的链接的完全解析目标readlink -f
:检查它是否以 开头$view/
。以下代码片段列出了所有转义链接,无论是否断开: