findコマンド後のコネクターの使用


10

私のbashは、findコマンドを使用して、何かが見つかった場合にのみ「found」を出力します。しかし、&&を使用しても効果はありません。何も見つからない場合でも、「見つかりました」と印刷されます。例:

$ pwd
/data/data/com.termux/files/home/test/test1/test4
$ ls
xaa  xab
$ find . -name xac && echo 'found'
found
$ find . -name xaa && echo 'found'
./xaa
found

回答:


18

あなたfind自身を印刷することができますfound

find . -name xac -printf "found\n" -quit

-quitようになりますfind 最初の試合後に辞めので、found一度だけ最大で印刷されます。

UnixとLinuxの同様のスレッド(何も見つからなかった場合にfindを失敗させる)では、何も見つからなかったgrep -qz場合にゼロ以外の終了ステータスを返していfindました。

find /some/path -print0 -quit | grep -qz .

&&またはを使用して複合コマンドを作成するために使用できるものif

find /some/path -print0 -quit | grep -qz . && echo found

私はしばらく見つめなければなりませんでした。 /some/pathどこから探し始めるかを指示しますが、何を探すべきかはわかりません。あなたのリンクされた答えでも同じです。私にとって何がうまくいくかですfind /some/path -name xac -print0 -quit | grep -qz . && echo found。私は何か見落としてますか?
Joe、

ここで重要なのは@Joe -print0 -quitです。その前に何を置くかは、あなたが見つけたいものに依存します。ここでは省略しました。
muru

13

muruの回答は適切であり、ファイルが見つかった場合に何かを印刷したい場合に適しています。などの外部コマンドを実行する場合の一般的なケースでは、フラグechoを使用できます-exec

$ find . -name 'xac' -exec echo "I found " {} \; -quit             
I found  ./xac

{}一部は間のコマンドにファイル名を渡す-execと、\;引数として。\前に注意してください;-シェルが誤って解釈するのを防ぎます;シェルの終了セミコロンはコマンドの終わりを示しますが、スラッシュでエスケープすると、シェルはそれをfindコマンドに渡されるリテラルテキストとして扱い、コマンドを見つけるために終了-execフラグの引数として機能します。


if found do this; else do that並べ替えの条件文$()を作成するために、コマンドの置換とtestコマンド(別名[)を利用できます。

$ [ "x$(find . -name 'noexist' -print -quit)" != "x" ] && echo "found" || echo "not found"                                                                                              
not found

$ [ "x$(find . -name 'xac' -print -quit)" != "x" ] && echo "found" || echo "not found"                                                                                                  
found

ダンのコメントへの対応

コメントのダンは尋ねました:

「私が見つけた{}」をエコーするのは、「私が見つけた」{}をエコーするよりも良いのではないですか?エコーの場合は問題ないかもしれませんが、誰かがコマンドをコピーしてエコーを別のコマンドに置き換えると、問題が発生する可能性があります

最初に問題を理解しましょう。通常、シェルには単語分割の概念があります。これは、引用符で囲まれていない変数と位置パラメータが展開され、個別のアイテムとして扱われることを意味します。たとえば、あなたが変数を持っている場合var、それが含まれているhello worldテキストをあなたが行うとき、touch $varシェルは、2つの個別の項目にそれを打破しますhelloと、worldtouchあなたは2つの別々のファイルを作成しようとしていたかのようにそれを理解します。実行するtouch "$var"と、シェルはhello world1つのユニットとして扱い、1 touchつのファイルのみを作成します。これは、シェルがどのように機能するかによってのみ発生することを理解することが重要です。

対照的に、findコマンドはfindそれ自体で処理され、execvp()システムコールによって実行されるため、このような動作の影響を受けません。したがって、シェルは関与しません。中かっこは、シェルでは特別な意味を持っていますがfind、最初ではなくコマンドの途中に表示されるため、この場合、シェルには特別な意味はありません。ここに例があります。いくつかの難しいファイル名を作成し、それらをstatコマンドの引数として渡してみましょう。

$ touch with$'\t'tab.txt with$' 'space.txt with$'\n'newline.txt

$ find -type f -exec stat -c "%F" {} \; -print                                                                                                                         
regular empty file
./with?newline.txt
regular empty file
./with space.txt
regular empty file
./with?tab.txt

ご覧のとおり、でstat難しいファイル名を完全に正常に受信しますfind。これは、ポータブルスクリプトでの使用が推奨される主な理由の1つであり、ディレクトリツリーをトラバースしていて、それらの特殊文字。したがって、で実行されるコマンドの波括弧を引用する必要はありませんfind

シェルが関与するときは別の話です。ファイル名を処理するためにシェルを使用する必要がある場合があります。その場合、引用は確かに重要ですが、問題が見つからないことを認識することが重要です。単語分割を行うのはシェルです。

$ find -type f -exec bash -c "stat {}" sh \;   
stat: cannot stat './with': No such file or directory
sh: line 1: newline.txt: command not found
stat: cannot stat './with': No such file or directory
stat: cannot stat 'space.txt': No such file or directory
stat: cannot stat './with': No such file or directory
stat: cannot stat 'tab.txt': No such file or directory

したがって、shell内で引用すると、機能します。しかし、繰り返しになりますが、それはシェルではなく、にとって重要ですfind

$ find -type f -exec bash -c "stat -c '%F' '{}'" sh \;                                                                                                                 
regular empty file
regular empty file
regular empty file

echo "I found {}"より良いのではないでしょうecho "I found " {}か?多分、echoの場合は問題ありませんが、コマンドをコピーしてechoを別のコマンドに置き換えると、問題が発生する可能性があります。
Dan

@Danトピックはコメントで議論するには長すぎたので、私は私の回答を編集しました。ご覧ください
Sergiy Kolodyazhnyy 2017年

1
セミコロンがなぜそこにある必要があるのか​​を理解してくれてありがとう。また、引用の素晴らしい説明。
Joe

1
私のコメントへの返信としてそれほど多くの詳細を期待していませんでした。その説明に感謝します、ありがとう!
Dan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.