2009-05-22 12 views
100

1は、ファイルの非常に大規模なセットをより効率的であり、使用すべきですか?find -exec cmd {} + vs | xargsの

find . -exec cmd {} + 

または

find . | xargs cmd 

(ファイル名には変な文字が存在しないと仮定)

+0

関連:https://stackoverflow.com/questions/9612090/how-to-loop-through-file-names-returned-by-find –

答えて

94

速度の差は重要ではありません。

は、しかし、あなたは確認する必要があり、その:

  1. あなたのスクリプトは何 ファイルが ファイル名になどのスペース、タブを、持っていないことを前提としません。最初のバージョンは で、2番目のバージョンは安全ではありません。

  2. スクリプトでは、「-」で始まるファイルはオプションとして扱われません。

    find . -exec cmd -option1 -option2 -- {} + 
    

    または

    find . -print0 | xargs -0 cmd -option1 -option2 -- 
    

    最初のバージョンは、あなたが1を無視することができるよう書き込むために短く、簡単ですが、 番目のバージョン:

だからあなたのコードは次のようになります。 「-exec cmd {} +は」GNUののfindutilsでは比較的新しいオプションであるとして、よりポータブルかつ安全である(2005年以降、システムを実行しているの多くはまだそれを持っていません)、それはました。他の回答からも分かるように、多くの人がこの "-exec cmd {} +"を知らない。

+4

-print0はGNU find(およびGNU xargs)オプションです。 Linux以外のシステムの多くから、移植性の議論は有効ではありません。しかし、-printを使いxargsを-0のままにしておくと、*は非常に移植性があります。 – dannysauer

+4

ポイントは、-print0を指定しないと、スペースやタブなどのファイルがあると動作しません。これは、 "foo -o index.html"のようなファイル名が存在する場合と同様にセキュリティ上の脆弱性があります。オプションとして扱われます。空のディレクトリ "touch - foo \ -o \ index.html; find。| xargs cat"を試してください。 "cat:無効なオプション - 'o'" – Tometzky

+2

彼の例は、 - を含むファイル名です。 -print0を指定しないと、findは./foo -o index.htmlを吐き出します。だから多分大したことではないかもしれませんが、結果はほとんど変わらず、マルチユーザシステムでは、あなたのスクリプトが世界で読めるものであれば攻撃ベクトルを提供することができます。 – bobpaul

7
find . | xargs cmd 

は、より効率的である(それは、execとは異なり、できるだけcmdとして数回実行しますマッチごとにcmdを1回実行します)。しかし、ファイル名にスペースやファンキーな文字が含まれていると、問題が発生します。

次を使用することが示唆されています

find . -print0 | xargs -0 cmd 

これは、ファイル名がファンキーな文字が含まれている場合でも動作します(-print0-0xargsは、このフォーマットを期待していますfind印刷NUL終端マッチを、作る。)

+25

これは ではありません "find。-exec cmd {} \;" しかし "-exec CMD {} +を見つけます"。後者は一度に1つのファイルを実行しません。そこには(または少数の)一致するファイルはありませんと 'cmd'は、各ファイルに対して行うことが多くを持っていない場合は' xargs'のアプローチは、実際にかなり遅いこと – Tometzky

+2

注意。空のディレクトリで実行したときに2つのプロセスがただ一つの代わりに開始されなければならないので、たとえば、 'xargs'のバージョンは、少なくとも2倍の時間がかかります。 (もちろん、違いは* nixでは普通は分かりませんが、ループの中では重要かもしれませんが、Windowsでしばらく試してみてください...) – SamB

関連する問題