find
最初の一致を見つけた後にコマンドを強制的に停止する方法はありますか?
答え1
GNUまたはFreeBSDの場合は述語をfind
使用できます-quit
。
find . ... -print -quit
NetBSDにfind
対応:
find . ... -print -exit
名前だけを印刷し、ファイル名に改行文字が含まれていないと仮定すると、次のことができます。
find . ... -print | head -n 1
これは最初のゲーム以降は停止しませんがfind
、2番目のゲームのタイミングとバッファリングによって、または(ずっと)後で停止することもできます。デフォルトでは、何かを出力しよfind
うとするとSIGPIPEで終了し、head
入力の最初の行を読んで表示したため、すでに終了しています。
find
このコマンドが返された後、すべてのシェルが待機するわけではありませんhead
。 BourneシェルおよびAT&T実装ksh
(非対話型の場合)およびyash
(パイプがスクリプトの最後のコマンドである場合にのみ)バックグラウンドで実行されません。どのシェルでもこの動作を確認するには、いつでも上記の内容を次のように変更できます。
(find . ... -print &) | head -n 1
見つかったファイルのパスを印刷する以外の操作を実行するには、次のことを試すことができます。
find . ... -exec sh -c 'printf "%s\n" "$1"; kill -s PIPE "$PPID"' sh {} \;
(printf
ファイルに必要なものに置き換えます)。
find
これには終了ステータスを返す副作用があり、終了ステータスを反映しています。
パイプラインの一部が信号によって終了したときに一部のシェルが表示するメッセージを避けるために、デフォルトのSIGTERM信号の代わりにSIGPIPE信号を送信します。 SIGPIPEによる死亡は自然に発生するため(上記のようにfind | head
...)通常、これは行われません。
答え2
find . -name something -print -quit
最初の一致を印刷して検索を終了します。
特定の数だけ一致した場合、検索を終了して結果を印刷します。
find . -name something -print | head -n 5
驚くべきことに - headは5回の一致の後に文字列を終了します。しかし、方法と理由はわかりません。
テストするのはとても簡単です。ただ検索してみてくださいㅏルートでは数千以上の一致が発生し、少なくとも1分以上かかります。ただし、「head」がパイプされると、「find」は指定された回数後に終了します。ワイヤーhead で定義されます。デフォルトのheadは10を表示し、「head -n」を使用して行を指定します。
これは、「head -n」が指定された改行の数に達した後に終了するため、複数の改行を含むすべての一致がそれに応じて計算されます。
答え3
findを実行するときは、その後にuseを追加してください-exec
。それ以外の場合、コマンドの実行は省略されます。たとえば、-quit
\;
find -name "myfile*" -exec echo "Found {} and Quit" \; -quit
Found ./myfile1 and Quit
しかし、-quitを使うと今後-実現する:
find -name "myfile*" -quit -exec echo "Found {} and Quit" \;
# Nothing was executed
答え4
-m
grepもflagで使用すると返されます。
find stuff | grep -m1 .
findによって印刷された最初の行の後に返されます。
これの違いは、find stuff -print -quit | head -1
検索が十分に速い場合、grepは時間内にプロセスを停止できない可能性がありますが(それは問題ではありません)、検索が長い場合は不要な多くの印刷からfindを保存することです。輪郭。
これはbusybox findで動作しますが、busybox grepもサポートしているので、-m
実際には必要ありません。
find /tmp/stuff -exec "sh" "-c" "eval 'echo {}; { kill \$PPID; }'" \;
これは find プロセスが (通常) sigterm シグナルを受け取ったというメッセージを出力しますが、この出力は find コマンドではなく実行中のシェルに属するため、コマンド出力を妨げません。出力行が照会と一致します。