再帰 grep と find/-type f -exec grep{}\;どちらがより効率的で速いですか?

再帰 grep と find/-type f -exec grep{}\;どちらがより効率的で速いですか?

ファイルシステム全体で文字列を含むファイルを見つけるために、再帰的なgrepとgrepを使用してexecステートメント内で検索する方が効率的ですか?ファイル拡張子やファイル名と一致する正規表現を知っていれば、少なくともフィルタリングを実行できますが、-type fどちらが良いかを知ることができるので、 find がより効率的であると思います。 GNU grep 2.6.3;検索(GNU findutils)4.4.2

例:

grep -r -i 'the brown dog' /

find / -type f -exec grep -i 'the brown dog' {} \;

ベストアンサー1

私は全く知りません:

grep -r -i 'the brown dog' /*

それがまさにあなたが意味したものです。これは、隠されていないすべてのファイルとディレクトリに対して繰り返しgrepを実行することを意味します/(ただし、まだその中にある隠しファイルとディレクトリを見てください)。

あなたが意味すると仮定すると:

grep -r -i 'the brown dog' /

参考にするいくつかの点があります。

  • すべてのgrep実装がこれをサポートする-rわけではありません。いくつかは、ディレクトリツリーをナビゲートするときにディレクトリのシンボリックリンクに従います(これは同じファイルを何度も表示することも、ループで無限に実行されることもあります)。 'ティー。一部はデバイスファイル(たとえばかなり長い時間がかかります/dev/zero)やパイプやバイナリを見ていますが、一部はそうではありません。
  • grepファイルが見つかるとすぐにファイル内を検索し始めるので、うまく機能します。ただし、ファイルを検索すると、検索するファイルはもう見つかりません(ほとんどの場合も同様です)。

あなたの:

find / -type f -exec grep -i 'the brown dog' {} \;

-rここでは言葉にならないものを削除しました。)grepファイルごとに1つずつ実行するので、非常に非効率的です。;1つの引数のみを許可するコマンドでのみ使用できます。そして、ここではgrep1つのファイルしか探していないので、ファイル名は印刷されないので、一致するものがどこにあるのかわかりません。

デバイスファイル、パイプ、シンボリックリンクを見ず、シンボリックリンクに従わないが、それでも/proc/mem

find / -type f -exec grep -i 'the brown dog' {} +

grepできるだけ少ないコマンドが実行されるため、はるかに優れています。最後の実行にファイルが1つしかない場合は、ファイル名を取得します。これを行うには、以下を使用するのが最善です。

find / -type f -exec grep -i 'the brown dog' /dev/null {} +

またはGNUを使用してくださいgrep

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アクセスすると、ディスクヘッドが継続的に移動し、ディスクスループットが低下します。これはgrepRAID設定(他のディスクにアクセスfindできるgrep)またはSSDに良い影響を与える可能性があります。

RAID設定で複数実行同時に grep電話をかけると状況が改善する可能性があります。まだ3つのディスクRAID1ストレージでGNUツールを使用しています。

find / -type f -print0 | xargs -r0 -P2 grep -Hi 'the brown dog'

パフォーマンスが大幅に向上する可能性があります。ただし、grep最初のコマンドを入力するのに十分なファイルが見つかるまで、2番目のgrepコマンドは開始されません。このタスクがより速く実行されるように(および呼び出しごとに少ないファイル数を渡すように)-nオプションを追加できます。xargsgrep

xargsまた、出力をターミナルデバイス以外のものにリダイレクトすると、grepssは出力バッファリングを開始します。これはgrep、対応するsの出力が誤ってインターリーブされる可能性があることを意味します。 (GNUまたはFreeBSDで利用可能な場合)(非常に長い行(通常4KiB以上)のためにまだ問題がある可能性があります)を使用してこの問題を解決するか、stdbuf -oL各出力を別々のファイルに書き込んで最後にすべて接続する必要があります。

ここで探している文字列は固定されているので(正規表現ではない)、そのオプションを-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 {} +

おすすめ記事