「検索」で一致するものが見つかったかどうかを検出する方法


16

「検索」で一致するものが見つかったかどうかを検出する慣用的な手段はありますか?私は現在使用しています

COUNT=`find ... | wc -l`
if [ "$COUNT" -gt 0 ]; then

しかし、これは私には少し間接的なようです。また、一致が見つかったら検索を停止したいので、時間と労力を無駄にしません。一致するファイルがあるかどうかを知る必要があるだけです。

更新:私は自分の前にコードなしで質問を書くのを間違えました:私wc -lは別のケースで使用します、とにかく見つかったファイルの総数を知る必要があります。一致するものがあるかどうかだけをテストする場合、を使用していましたif [ -z $(find …) ]

回答:


17

GNU findがあることがわかっている場合は、を使用-quit して、最初の一致後に停止します。

移植性があるため、の出力をfindにパイプしますhead -n 1。その方法findは、数回一致した後(パイプheadの入力バッファがいっぱいになったとき)パイプが壊れて死にます。

いずれにしてもwc、文字列が空であるかどうかをテストする必要はありません。シェルはそれを単独で実行できます。

if [ -n "$(find … | head -n 1)" ]; then …

興味深い... -n「定義済み」変数($ abc、$ xyzなど)にのみ適用されると考えましたが、$(...)は「定義済み」の一時変数であると思います。-n変数をまだ宣言しておらず、「未使用」であることが確かでない限り、使用は危険であると最近読んでください...しかし、tempにはこの可能性はありません... 未初期化と空
Peter.O

2
@fred:それどころか、-n文字列が空かどうかをテストします。変数とは関係ありません。あなたが読んだことは、おそらくusing -nは変数が定義されているかどうかをテストしないと言っていました:定義されているが空の-n "$foo"場合fooはfalseで、の下にエラーメッセージを表示しますset -u。が設定されている[ -n "${foo+1}" ]かどうかを確実にテストしますfooが、空の変数と設定されていない変数を同じように扱うことは、通常は良い考えです:[ -n "${foo:+1}" ]、または単に[ -n "$foo" ]心配しない場合set -u
ジル「SO-停止されて悪」

ありがとう!私は-quit利用できませんが、パイピングはhead -n 1機能します(機能しますがhead -c 1、それはさらに早く停止しますが、おそらく無視できる利益があります)。また、目の前のコードなしで質問を書くことを間違えました:wc -l見つかったファイルの総数を知る必要がある別のケースで使用します。一致するものがあるかどうかだけをテストする場合、を使用していましたif [ -z `find … ` ]
クリスページ

6

-quitアクションを使用して、最初の一致後に停止できます。おそらくそれを別のアクション(など-print)と組み合わせたいと思うでしょう。さもなければ、それが何かを見つけたかどうかを見分けることができないでしょう。

たとえばfind ... -print -quit、最初に一致したファイルのパスを出力して終了します。または、-printf 1 -quit一致する場合は1を印刷し、一致しない場合は何も印刷しません。

findの終了ステータスは、検索中にエラーが発生したかどうかを反映し、何かを検出したかどうかを反映しないため、一致するかどうかを確認するには出力を確認する必要があります。


-quitGNU拡張機能です。OS X、BSD、およびおそらくほとんどの商用Unicesなど、find(1)の他の実装を使用するシステムでは動作しません。
ウォーレンヤング

おかげで、別のシステムを使用している場合に知っておくと便利です。残念ながら、-quitも-printfも私の(Mac OS X)では利用できません。
クリスページ

4

終了0は検索で簡単ですが、終了> 0は通常はエラーでのみ発生するため、より困難です。ただし、それを実現することはできます。

if find -type f -exec false {} +
then
  echo 'nothing found'
else
  echo 'something found'
fi

このソリューションは、サブシェルを使用するよりもパフォーマンスが高いことに注意してください。falseの実行は、Dashの実行よりも確かに高速です。

$ cat alfa.sh bravo.sh charlie.sh delta.sh
find -name non-existing-file -exec false {} +
find -name existing-file -exec false {} +
[ "$(find -name non-existing-file)" ]
[ "$(find -name existing-file)" ]

$ strace dash alfa.sh | wc -l
807

$ strace dash bravo.sh | wc -l
1141

$ strace dash charlie.sh | wc -l
1184

$ strace dash delta.sh | wc -l
1194

0

シェル条件にラップすることができます、例えば:

[ "$(find . ...)" '!=' '' ] && echo Found || echo Not found

...一致条件はどこにありますか(例:)-name *.txt

他の例:

[ "$(find /etc -name hosts)" ] && echo True || echo False
[ ! -z "$(find /etc -name hosts)" ] && echo True || echo False
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.