ファイルシステム全体のどのファイルに文字列が含まれているかを見つけるのに、どちらがより効率的ですか?再帰的なgrepまたはexecステートメントのgrepで検索しますか?ファイル拡張子またはファイル名と一致する正規表現がわかっている場合でも、 -type f しかわからない場合は、少なくともある程度のフィルタリングを実行できるため、findの方が効率的だと思います。 どちらがいいですか? GNU grep 2.6.3; find(GNU findutils)4.4.2
例:
grep -r-i'茶色の犬'/
find / -type f -exec grep-i'茶色の犬'{};
承認された回答:
よくわかりません:
grep -r -i 'the brown dog' /*
本当にあなたが意味したことです。これは、 /内のすべての非表示ファイルとdirsで再帰的にgrepを実行することを意味します。 (ただし、非表示のファイルとそれらの内部のdirsの内部を確認してください)。
あなたが意味したと仮定して:
grep -r -i 'the brown dog' /
注意すべき点:
- すべての
grepではありません 実装は-rをサポートします 。また、動作は異なります。ディレクトリツリーをトラバースするときにディレクトリへのシンボリックリンクをたどる場合もあります(つまり、同じファイルを何度も検索したり、無限ループで実行したりする場合もあります)。デバイスファイルの内部を調べる人もいます(/ dev / zeroではかなり時間がかかります) たとえば)またはパイプやバイナリファイル…、そうでないものもあります。 -
grepとして効率的です ファイルが見つかるとすぐにファイルの内部を調べ始めます。ただし、ファイルを検索している間は、検索するファイルをさらに探す必要はありません(ほとんどの場合、これはおそらく同じです)
あなた:
find / -type f -exec grep -i 'the brown dog' {} ;
( -rを削除しました ここでは意味がありませんでした)1つの grep を実行しているため、非常に非効率的です。 ファイルごと。 ;コード> 1つの引数のみを受け入れるコマンドにのみ使用する必要があります。さらにここでは、 grep 1つのファイルのみを検索し、ファイル名を出力しないため、一致する場所がわかりません。
デバイスファイル、パイプ、シンボリックリンクの内部を調べていません…、シンボリックリンクをフォローしていませんが、 / proc / memのようなものの内部を調べている可能性があります 。
find / -type f -exec grep -i 'the brown dog' {} +
grep が少ないので、はるかに優れています 可能な限りコマンドが実行されます。最後の実行でファイルが1つしかない場合を除いて、ファイル名を取得します。そのためには、以下を使用することをお勧めします:
find / -type f -exec grep -i 'the brown dog' /dev/null {} +
またはGNUgrepを使用 :
find / -type f -exec grep -Hi 'the brown dog' {} +
grepに注意してください findまで開始されません 噛むのに十分なファイルが見つかったため、初期遅延が発生します。そしてfind 前のgrepまで、さらにファイルの検索を続行しません 帰りました。大きなファイルリストの割り当てと受け渡しは、(おそらく無視できる程度の)影響を与えるため、全体として、 grep -rよりも効率が低下する可能性があります。 シンボリックリンクをたどったり、デバイスの内部を見たりすることはありません。
GNUツールの場合:
find / -type f -print0 | xargs -r0 grep -Hi 'the brown dog'
上記のように、わずかな grep 可能な限りインスタンスが実行されますが、 find 最初のgrepの間、さらにファイルを探し続けます 呼び出しは最初のバッチの内部を調べています。しかし、それは利点かもしれないし、そうでないかもしれません。たとえば、回転式ハードドライブにデータが保存されている場合、 find およびgrep ディスクのさまざまな場所に保存されているデータにアクセスすると、ディスクヘッドが常に移動するため、ディスクのスループットが低下します。 RAIDセットアップの場合( find およびgrep 異なるディスクにアクセスする可能性があります)またはSSDで、それはプラスの違いを生む可能性があります。
RAIDセットアップで、複数の同時を実行する grep 呼び出しも物事を改善する可能性があります。 3つのディスクを備えたRAID1ストレージ上のGNUツールを引き続き使用します。
find / -type f -print0 | xargs -r0 -P2 grep -Hi 'the brown dog'
パフォーマンスが大幅に向上する可能性があります。ただし、2番目の grep 最初のgrepを埋めるのに十分なファイルが見つかった場合にのみ開始されます 指図。 -nを追加できます xargsのオプション それがより早く起こるために(そして grepごとにより少ないファイルを渡すために 呼び出し)。
xargsをリダイレクトする場合にも注意してください 端末デバイス以外に出力してから、 greps sは出力のバッファリングを開始します。これは、これらの grepの出力を意味します。 sはおそらく誤ってインターリーブされます。 stdbuf -oLを使用する必要があります (GNUやFreeBSDのように利用可能な場合)それを回避するか(非常に長い行(通常は> 4KiB)で問題が発生する可能性があります)、またはそれぞれが出力を別々のファイルに書き込んで、最後にすべてを連結します。
ここでは、探している文字列が固定されているため(正規表現ではない)、 -Fを使用します。 オプションが違いを生む可能性があります( grep とは異なります) 実装はそれをすでに最適化する方法を知っています。
マルチバイトロケールを使用している場合、大きな違いを生む可能性のあるもう1つのことは、ロケールをCに修正することです。
find / -type f -print0 | LC_ALL=C xargs -r0 -P2 grep -Hi 'the brown dog'
/ procの内部を見ないようにするため 、 / sys …、 -xdevを使用します 検索するファイルシステムを指定します:
LC_ALL=C find / /home -xdev -type f -exec grep -i 'the brown dog' /dev/null {} +
または、明示的に除外するパスを削除します:
LC_ALL=C find / ( -path /dev -o -path /proc -o -path /sys ) -prune -o
-type f -exec grep -i 'the brown dog' /dev/null {} +