我有以下目錄樹:
.
└── aaa
└── bbb
└── ccc
並建立符號連結:
ln -s ~/test/aaa/bbb slink
之後我運行樹命令:
tree -l
並看到
.
├── aaa
│ └── bbb
│ └── ccc
└── slink -> /home/kaa/test/aaa/bbb [recursive, not followed]
為什麼slink被標記為遞迴?這是一個錯誤還是我誤解了什麼?
答案1
您使用了以下-l
選項:
如果符號連結指向目錄,則遵循符號鏈接,就像它們是目錄一樣。偵測到會導致遞歸的符號連結時會避免。
現在,它印出此警告的原因並不是它會實際上遞迴.我們可以清楚地看到它只是bbb/ccc
再次列出樹。
對應的代碼是這裡, 順便一提。如果在哈希表(用saveino
和填充的哈希表)中找到符號連結指向的目錄的 inode 號findino
,它將簡單地跳過它。
答案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