最初の一致を見つけた直後にfind
コマンドを強制的に停止する方法はありますか?
GNUまたはFreeBSD find
を使用すると、-quit
述語を使用できます。
find . ... -print -quit
同等のNetBSD find
:
find . ... -print -exit
名前を印刷するだけで、ファイル名に改行文字が含まれていないと想定すると、次のようにできます。
find . ... -print | head -n 1
最初の一致の後でfind
が停止することはありませんが、2番目の一致時または(かなり)後のタイミングとバッファリングに応じて可能性があります。基本的に、find
は、入力の最初の行を既に読み取って表示しているため、head
がすでになくなっている間に何かを出力しようとすると、SIGPIPEで終了します。
find
が返された後、すべてのシェルがそのhead
コマンドを待機するわけではないことに注意してください。 Bourne ShellおよびAT&Tのksh
(非対話型の場合)とyash
(そのパイプラインがスクリプトの最後のコマンドの場合のみ)の実装では、バックグラウンドで実行されたままになります。シェルでその動作を確認したい場合は、常に上記を次のように変更できます。
(find . ... -print &) | head -n 1
見つかったファイルのパスを出力するだけではない場合は、次の方法を試すことができます。
find . ... -exec sh -c 'printf "%s\n" "$1"; kill "$PPID"' sh {} \;
(printf
を、そのファイルで実行することになるものに置き換えます)。
これには、find
が強制終了されたという事実を反映して終了ステータスを返すという副作用があります。
実際には、SIGTERMの代わりにSIGPIPEシグナル(kill
の代わりにkill -s PIPE
)を使用すると、一部のシェルがその死についてより静かになります(ただし、ゼロ以外の終了ステータスが返されます)。
find . -name something -print -quit
印刷後、最初の一致後にfindを終了します。
特定の数の一致の後にfindを終了し、結果を印刷します。
find . -name something -print | head -n 5
意外にも十分です。方法や理由はわかりませんが、headは5回一致した後に文字列を終了します。
テストは非常に簡単です。ルートで検索aを見つけさせてください。少なくとも1分以上かかりますが、数千、場合によってはさらに多くの一致が得られます。ただし、「head」にパイプすると、「find」は指定した量のlinesがヘッドで定義された後に終了します(デフォルトのヘッドは10を示し、「head -n」を使用してラインを指定します)。
これは、「head -n」が指定された改行文字数に達した後に終了するため、複数の改行文字を含むすべての一致がそれに応じて数えられることに注意してください。
エンターテインメントの目的で、Bashの遅延検索ジェネレータを次に示します。この例では、現在のディレクトリのファイルにリングを生成します。好きなだけ読んでくださいkill %+
(たぶん1)
#!/usr/bin/env bash
unset -v files n
trap 'kill "$x_PID"' EXIT
coproc x while :; do
find . -type f -maxdepth 1 -exec sh -c "$(</dev/fd/3)" _ {} +
done 4<&0 <<\EOF 3<&0 <&4-
for x; do
read -r _
printf '%s\0' "$x"
done
EOF
while
echo >&${x[1]}
IFS= read -rd '' -u "$x" 'files[n++]'
do
printf '%q ' "${files[@]}"
echo
sleep .2
done
フラグ-m
と一緒に使用すると、grepも返されるため、
find stuff | grep -m1 .
findによって出力された最初の行の後に戻ります。
これとfind stuff -print -quit | head -1
の違いは、検索が十分に高速である場合、grepは時間内にプロセスを停止できない可能性があります(実際には問題ではありません)。多くの不要な行。
これは代わりにbusybox findで機能しますが、busybox grepにも-m
があるため、実際には必要ありません
find /tmp/stuff -exec "sh" "-c" "eval 'echo {}; { kill \$PPID; }'" \;
これは、(通常)sigtermシグナルを受信したfindプロセスに関するメッセージを吐き出しますが、この出力は、findコマンドではなく、実行中のシェルに属しているため、コマンド出力に干渉しません。つまり、パイプまたはリダイレクトは行のみを出力します検索で一致。