为什么树命令将符号链接标记为递归?

为什么树命令将符号链接标记为递归?

我有以下目录树:

.
└── 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功能findinohash.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

相关内容