Linux で特定のシンボリックリンクをたどりながら「検索」するにはどうすればよいですか?

Linux で特定のシンボリックリンクをたどりながら「検索」するにはどうすればよいですか?

ファイル(類似の機能を持つもの)を検索したいのですfindが、特定のシンボリックリンクのみを(パターン マッチングによって)追跡します。

どうやらfindそれ自体ではそれを処理できないようです。シンボリックリンクのフォロー動作を設定するオプションがなく、単純な操作ではfind -L簡単にロックが発生します (または非常に遅くなります)。

答え1

質問の最後の文は、問題が一般的なシンボリックリンクのフォロー(例えば、-newerあるケースではシンボリックリンクに適用され、別のケースではターゲットに適用される)ではなく、シンボリックリンクのフォローにあることを示唆しています。ディレクトリへそして、望まない場所に降りてしまいます。

パー仕様は、find無限ループを検出するので、ライブロックは発生しません。リソース (時間を含む) が無駄になることが問題になる可能性があり、あなたの懸念は理解できます。

まず、 を使用して、たどってほしいシンボリックリンクをたどること-Lを許可します。次に、他のシンボリックリンクを検出する方法が必要です。find

は決してfind -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およびシェル コードが必要です。例:

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を作成し、最後にその他すべてのシンボリックリンクを作成します。quxbaz-prune

ノート:

  • realpathbasename持ち運びできません。
  • realpathすべてのシンボリックリンクを解決します。
  • シンボリックリンクが壊れている場合の動作は、期待どおりになる場合もそうでない場合もあります。
  • ファイルごとに を個別に呼び出すとtestパフォーマンスが低下しますが、これより良い方法は見つかりませんでした。shrealpath、を呼び出すbasenameこともこの問題では良くありませんが、ここではシンボリックリンクに対してのみ発生するため、ほとんどの場合、影響は限定されます。
  • find-shここで説明されています:の2番目のshは何ですかsh -c 'some shell code' sh?
  • 例では、-pruned されたパス名は ed されません-print。最後の部分を に変更する-prune -false -o -printと、出力されます。説明-false;必要な場合に備えて、のポータブルな代替手段があります。

関連情報