回答:
GNUまたはFreeBSD find
では、次の-quit
述語を使用できます。
find . ... -print -quit
find
同等のNetBSD :
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 "$PPID"' sh {} \;
(printf
そのファイルで行うことを何でも置き換えてください)。
これには、find
終了ステータスが返されるという副作用がありますが、終了ステータスは強制終了されたという事実を反映しています。
実際には、(SIGTERMの代わりにSIGPIPE信号を使用してkill -s PIPE
代わりにすることはkill
)一部のシェルは、その死についてもっと静かにさせるだろう(まだゼロ以外の終了ステータスを返します)。
if [[ $(find ... -print -quit) ]]; then ...
、印刷されたものを見つけるかどうかだけです。
$(…)
単一の角かっこ([ … ]
)のみを使用している場合に備えて、引用符で囲んだ方が良いでしょう。
[
は標準コマンドです。恐ろしいのはコマンドではなく、Bourneのようなシェルがコマンドラインを解析する方法です。[[...]]
さまざまなシェルに独自の問題があるkshコンストラクトです。たとえば、最近まで[[ $(...) ]]
動作しませんでしたzsh
(必要です[[ -n $(...) ]]
)。除いてzsh
、あなたが引用符を必要とし[[ $a = $b ]]
、[[ =~ ]]
実装の間、さらにいくつかの中のbash用のバージョンと互換性のないいくつかのバグとの間に違いがあります。個人的に、私は好む[
。
...
?。
find . -name something -print -quit
印刷後に最初に一致した後にfindを終了します。
特定の量の一致後に検索を終了し、結果を出力します。
find . -name something -print | head -n 5
驚くべきことに-headは5回の一致の後に文字列を終了させるようになりましたが、方法や理由はわかりません。
テストは非常に簡単です。少なくとも1分以上かかりながら、数千、場合によってはさらに多くの一致を検索するルートを検索してください。しかし、「head」にパイプすると、「find」はheadで定義された指定された行数の後に終了します(デフォルトのheadは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
grepは、フラグとともに使用された場合にも返される-m
ため、
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コマンドではなく実行中のシェルに属しているため、コマンド出力を台無しにしないため、パイプまたはリダイレクトは行のみを出力します検索で一致。