find -exec + vs find | xargs:どちらを選択しますか?


32

の動作を模倣-execする+オプションを選択できることを理解していますxargs。あるフォームを他のフォームよりも好む状況はありますか?

個人的には、パイプの使用を避けるためだけに、最初の形式を好む傾向があります。開発者はfind適切な最適化を行ったに違いない。私は正しいですか?

回答:


21

呼び出しを連鎖させて検索することもできます(一度学習したときに、それが可能であること、今日かもしれません)。もちろん、これはfind内にいる限り可能です。xargsにパイプすると、スコープ外になります。

小さな例、2つのファイルa.lstとb.lst:

cat a.lst
fuddel.sh
fiddel.sh

cat b.lst
fuddel.sh

ここにトリックはありません-両方に「fuddel」が含まれているが、1つだけに「fiddel」が含まれているという事実。

私たちはそれを知らなかったと仮定します。2つの条件に一致するファイルを検索します。

find -exec grep -q fuddel {} ";" -exec grep -q fiddel {} ";" -ls
192097    4 -rw-r--r--   1 stefan   stefan         20 Jun 27 17:05 ./a.lst

おそらく、両方の文字列を条件として渡すgrepまたは別のプログラムの構文を知っているかもしれませんが、それはポイントではありません。引数としてファイルを指定すると、trueまたはfalseを返すことができるすべてのプログラムをここで使用できます。grepは一般的な例です。

また、-ls-deleteなどの検索コマンドを使用して、find -execを実行することもできます。deleteはrm(ファイルを削除する)だけでなく、rmdir(ディレクトリを削除する)も実行することに注意してください。

このようなチェーンは、特に指定されていない限り(つまり、-orスイッチ(および括弧(マスクが必要))を使用)、コマンドのANDの組み合わせとして読み取られます。

したがって、検索チェーンを離れることはありません。これは便利なことです。-xargsを使用しても利点はありません。ファイルの受け渡しには注意が必要です。これはfindで行う必要はありません。各ファイルの受け渡しを自動的に1つの引数として処理します。

{}ブレースを見つけるためにマスキングが必要だと思われる場合は、証拠を尋ねる私の質問に気軽にアクセスしてください。私の主張はこうです。


3
この投稿は新しい使い方に私の目を開いたfind。どうもありがとう!
rahmu

1
「-xargsを使用しても利点がありません」。4つのコアのうち3つがアイドル状態にならないようにする-exec方法は何xargs -P4ですか?
ダミアンジェリック16年

1
@DamianYerrick:「;」ではなく-execコマンドを終了する ただし、+(/プラス記号)を使用します。
ユーザー不明

25

ファイル名を安全にパイプxargsするにfindは、-print0オプションをサポートし、xargsそれを読み取るための対応するオプション(--nullまたは-0)が必要です。そうしないと、名前に印刷できない文字、バックスラッシュ、引用符、または空白が含まれるファイル名が予期しない動作を引き起こす可能性があります。一方、find -exec {} +POSIX find仕様に含まれているため、移植性があり、とほぼ同じくらい安全find -print0 | xargs -0で、間違いなくより安全ですfind | xargs。なしでは絶対にfind | xargsないことをおすすめし-print0ます。


6
find … -exec … {} +OpenBSD の注目すべき例外は、2012年にリリースされたバージョン5.1でのみこの機能を獲得した-print0OpenBSDです。一方、SolarisはPOSIXの機能に固執しているため、手に入れることは-exec +ありません-print0
ジル 'SO-悪であるのをやめる

-print0苦痛であり、あなたxargs --delimiter "\n"は同等ではないと主張することができますが、後者を発見した後、私は前者を一度も使用したことがありません。
シュリダールSarnobat

3
私はどのくらい-0痛みがあるかわかりません--delimiter "\n"
jw013

2
に加えて-0、入力がない場合、GNU はコマンドの実行を避けるxargs必要-rがあります。
ステファンシャゼル

2
別の問題| xargs -r0 cmdは、cmdの標準入力が影響を受けることです(xargs実装、それ、/dev/nullまたはパイプによって異なります。
StéphaneChazelas 15年

10

-exec ... ;フォームを使用する場合(セミコロンをエスケープすることを忘れないでください)、ファイル名ごとに1回コマンドを実行しています。を使用する場合-print0 | xargs -0、ファイル名ごとに複数のコマンドを実行します。間違いなく-exec +フォームを使用する必要があります。このフォームは、単一のコマンドラインに複数のファイルを配置し、多数のファイルが関係する場合ははるかに高速です。

を使用することの大きな利点xargsは、複数のコマンドを並行して使用できることxargs -Pです。マルチコアシステムでは、大幅に時間を節約できます。


6
あなたの-P代わりに-p。心に留めておくxargs -Pのに対し、POSIX標準ではなく、find -exec {} +あなたが移植のために行くされている場合に重要である、です。
jw013

@Alexiosシェルにとって特別な意味がないため、プラス記号をエスケープする必要はありませんfind /tmp/ -exec ls "{}" +。正常に動作します。
ダニエルクルマン

1
もちろん、コレント。私は-exec長い間、すべてをエスケープしていました(私はマゾです、エスケープするのに引用符を使用しません{}、常に入力し\{\}ます;尋ねないでください)、すべてが今エスケープされなければならないように見えます。
アレクシオス

1
@Alexios:ブレースのマスキングが有用な例(マゾであることを除く)を見つけた場合は、ここで私の質問への回答としてそれを提供してください-このヒントは古く、マンページに残っているだけです。find /tmp/ -exec ls {} +動作しない例を見たことはありません。
ユーザー不明

1
私にとっては、これはSunOS 4の時代に形成された筋肉の記憶です。何年もやってきたのでbash、中括弧を受け入れ始めたとき、私は完全に気づきませんでした。ブレースがエスケープされていない場合、私が使用した古いシェルの少なくとも1つがヒッシーフィットを投げたと確信しています。
-Alexios

8

パフォーマンスに関して-exec … +は、すべての作業を行う単一のツールであるため、単純に優れていると考えましたが、GNU findutilのドキュメントの一部で-exec … +は、場合によっては効率が低下する可能性があります。

[find with -exec … +]は、xargs;の一部の使用よりも効率が悪い場合があります。たとえばxargs、前のコマンドの実行中に新しいコマンドラインを作成できます。また、並行して実行するコマンドの数を指定できます。ただし、このfind ... -exec ... +構造には、幅広い移植性という利点があります。GNU findutilsは-exec ... +、バージョン4.2.12 [2005年1月]まで' 'をサポートしていませんでした。この理由の1つは、-print0いずれにせよ、既に ' 'アクションがあったことです。

私はそれが何を意味するのか正確にはわからなかったので、チャットでデロベルトがそれを説明した場所を尋ねました:

findおそらくファイルの-exec … +実行中に次のファイルのバッチを検索し続けることができますが、そうではありません。
find … | xargs …これは、findが別のプロセスであり、パイプバッファーがいっぱいになるまで実行を続けるためです。

(私によるフォーマット。)

それがあります。しかし、パフォーマンスが本当に重要な場合は、現実的なベンチマークを実行するか、そのような場合にシェルを使用するかどうかを自分で尋ねる必要があります。

このサイト-exec … +では、他の回答で説明されている理由より単純であるため、可能な限りフォームを使用するように人々にアドバイスする方が良いと思います(例えば、あまり考えずに奇妙なファイル名を処理する)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.