ファイルシステム全体のどのファイルに文字列が含まれているかを見つけるのに、どちらがより効率的ですか?再帰的な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 {} +