回答:
呼び出しを連鎖させて検索することもできます(一度学習したときに、それが可能であること、今日かもしれません)。もちろん、これは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つの引数として処理します。
{}ブレースを見つけるためにマスキングが必要だと思われる場合は、証拠を尋ねる私の質問に気軽にアクセスしてください。私の主張はこうです。
-exec
方法は何xargs -P4
ですか?
ファイル名を安全にパイプxargs
するにfind
は、-print0
オプションをサポートし、xargs
それを読み取るための対応するオプション(--null
または-0
)が必要です。そうしないと、名前に印刷できない文字、バックスラッシュ、引用符、または空白が含まれるファイル名が予期しない動作を引き起こす可能性があります。一方、find -exec {} +
はPOSIX find
仕様に含まれているため、移植性があり、とほぼ同じくらい安全find -print0 | xargs -0
で、間違いなくより安全ですfind | xargs
。なしでは絶対にしfind | xargs
ないことをおすすめし-print0
ます。
find … -exec … {} +
OpenBSD の注目すべき例外は、2012年にリリースされたバージョン5.1でのみこの機能を獲得した-print0
OpenBSDです。一方、SolarisはPOSIXの機能に固執しているため、手に入れることは-exec +
ありません-print0
。
-print0
苦痛であり、あなたxargs --delimiter "\n"
は同等ではないと主張することができますが、後者を発見した後、私は前者を一度も使用したことがありません。
-0
痛みがあるかわかりません--delimiter "\n"
。
-0
、入力がない場合、GNU はコマンドの実行を避けるxargs
必要-r
があります。
| xargs -r0 cmd
は、cmd
の標準入力が影響を受けることです(xargs
実装、それ、/dev/null
またはパイプによって異なります。
-exec ... ;
フォームを使用する場合(セミコロンをエスケープすることを忘れないでください)、ファイル名ごとに1回コマンドを実行しています。を使用する場合-print0 | xargs -0
、ファイル名ごとに複数のコマンドを実行します。間違いなく-exec +
フォームを使用する必要があります。このフォームは、単一のコマンドラインに複数のファイルを配置し、多数のファイルが関係する場合ははるかに高速です。
を使用することの大きな利点xargs
は、複数のコマンドを並行して使用できることxargs -P
です。マルチコアシステムでは、大幅に時間を節約できます。
-P
代わりに-p
。心に留めておくxargs -P
のに対し、POSIX標準ではなく、find -exec {} +
あなたが移植のために行くされている場合に重要である、です。
find /tmp/ -exec ls "{}" +
。正常に動作します。
-exec
長い間、すべてをエスケープしていました(私はマゾです、エスケープするのに引用符を使用しません{}
、常に入力し\{\}
ます;尋ねないでください)、すべてが今エスケープされなければならないように見えます。
bash
、中括弧を受け入れ始めたとき、私は完全に気づきませんでした。ブレースがエスケープされていない場合、私が使用した古いシェルの少なくとも1つがヒッシーフィットを投げたと確信しています。
パフォーマンスに関して-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 … +
では、他の回答で説明されている理由より単純であるため、可能な限りフォームを使用するように人々にアドバイスする方が良いと思います(例えば、あまり考えずに奇妙なファイル名を処理する)。
find
。どうもありがとう!