
我想要find
文件(具有類似的功能來查找),但遵循且僅遵循特定的符號連結(透過模式匹配)。
顯然find
它本身無法處理它:沒有選項可以設定符號連結跟隨行為;以及一個天真的find -L
輕鬆活鎖(或非常慢)。
答案1
問題的最後一句話表明問題不在於一般的以下符號連結(例如應用-newer
在一種情況下應用於符號鏈接,而在另一種情況下應用於目標),而是在於以下符號鏈接到目錄從而下降到你不想要的地方。
每規格,find
應檢測無限循環,因此不應發出生活鎖。資源(包括時間)的浪費可能是一個問題,我理解您的擔憂。
首先,使用-L
允許find
跟隨您希望它跟隨的符號連結。然後你需要一種方法來偵測其他符號連結。
Infind -L
-type l
從來都不是真的,但您可以檢測符號連結-exec test -L {} \;
(記住-exec … \;
這也是一個測試,當且僅當內部命令以狀態 0 退出時它才會成功)。這樣,您仍然可以相應地對符號連結應用一些測試和-prune
(或不)。
例如,以下命令將僅下降名稱以 開頭foo
或結尾的符號連結bar
:
find -L . -exec test -L {} \; ! \( -name 'foo*' -o -name '*bar' \) -prune -o -print
無論您最初想要什麼表達方式,都將其放在 後面-prune -o
。在上面的命令中,“原始”表達式是-print
。請記住-exec
抑制隱式-print
,因此如果您需要,-print
請明確添加它(就像我們所做的那樣)。
請注意,-name
測試符號連結本身的名稱。如果您想測試目標的名稱,那麼您可能需要realpath
,可能basename
還需要一些 shell 程式碼;例子:
find -L . -exec test -L {} \; -exec sh -c '
case "$(basename "$(realpath "$1")")" in
baz* ) exit 0 ;;
*qux ) exit 1 ;;
esac
exit 0
' find-sh {} \; -prune -o -print
上面的命令將-prune
任何符號連結到名稱以 開頭的任何文件baz
,但它將符號連結下降到名稱以 結尾的目錄qux
(除非以 開頭baz
),最後是-prune
所有其他符號連結。
筆記:
realpath
且不basename
便於攜帶。realpath
解析所有符號連結。- 符號連結損壞時的行為可能是也可能不是您所期望的。
- 為每個文件調用單獨的
test
文件會損害性能,但我沒有找到更好的方法。呼叫sh
,realpath
和basename
在這件事上也很糟糕,但這裡它只發生在符號鏈接上,所以在大多數情況下影響將是有限的。 find-sh
解釋如下:中的第二個 sh 是什麼sh -c 'some shell code' sh
?- 在範例中,取得
-prune
d 的路徑名將不會被-print
編輯。將最終片段更改為-prune -false -o -print
並且它們將被列印。看解釋;-false
如果您需要的話,有一個便攜式替代品。