我有以下目录树:
.
└── aaa
└── bbb
└── ccc
并创建符号链接:
ln -s ~/test/aaa/bbb slink
此后我运行 tree 命令:
tree -l
看看
.
├── aaa
│ └── bbb
│ └── ccc
└── slink -> /home/kaa/test/aaa/bbb [recursive, not followed]
为什么 slink 被标记为递归?这是一个错误还是我误解了什么?
答案1
您使用了以下-l
选项:
如果符号链接指向目录,则将其视为目录,然后继续跟踪。检测到会导致递归的符号链接时,会避免使用。
现在,它打印这个警告的原因不是因为它会实际上递归。我们可以清楚地看到,它只会bbb/ccc
再次列出树。
相应的代码是这里顺便说一下。如果在哈希表(用saveino
和填充的表findino
)中找到符号链接指向的目录的 inode 编号,它就会直接跳过它。
答案2
我认为文档不够准确。文档中说
符号链接将导致递归避免被发现
但它应该说类似
符号链接将导致已经访问过的目录未遵循
看错误信息的位置tree.c
和
功能findino
hash.c
。
tree -l
记住访问过的目录,并且只进入链接其目标还未被访问过:
( mkdir test1 && cd test1 && mkdir -p a/b && ln -s a link && tree -l; )
.
├── a
│ └── b
└── link -> a [recursive, not followed]
请注意,忽略已访问过的目录仅适用于链接。真实的目录总是被访问。这意味着遍历顺序很重要. 按照字母逆序 ( -r
) 遍历完全相同的树将跟随链接,因为它在访问链接时其目标仍未被访问。
( cd test1 && tree -r -l; )
.
├── link -> a
│ └── b
└── a
└── b
以下是重现此行为的另外两种方法:
忽略(-I
)目录a/
,这样访问链接时就认为该目录未被访问过:
( cd test1 && tree -l -I a; )
.
└── link -> a
└── b
命名目录和链接,以便自然地首先访问链接:
( mkdir test2 && cd test2 && mkdir -p x/y && ln -s x link && tree -l; )
.
├── link -> x
│ └── y
└── x
└── y