如何在 Linux 上追蹤特定符號連結時「查找」?

如何在 Linux 上追蹤特定符號連結時「查找」?

我想要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,realpathbasename在這件事上也很糟糕,但這裡它只發生在符號鏈接上,所以在大多數情況下影響將是有限的。
  • find-sh解釋如下:中的第二個 sh 是什麼sh -c 'some shell code' sh
  • 在範例中,取得-pruned 的路徑名將不會被-print編輯。將最終片段更改為-prune -false -o -print並且它們將被列印。看解釋;-false如果您需要的話,有一個便攜式替代品。

相關內容