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