数千ファイルのGrep


13

私はcca 26 000ファイルのディレクトリがあり、これらすべてのファイルでgrepする必要があります。問題は、できるだけ早くそれを必要とすることです。そのため、grepがfindコマンドから1つのファイルの名前を取得し、ファイルに一致を書き込むスクリプトを作成することは理想的ではありません。「引数リストが長すぎます」問題の前に、このすべてのファイルをgrepするのにccaに2分かかりました。それを行う方法はありますか?編集:常に新しいファイルを作成するスクリプトがあるため、すべてのファイルを異なるディレクトリに配置することはできません。


1
使用findしてxargsgrep -R
Eddy_Em

回答:


19

find

cd /the/dir
find . -type f -exec grep pattern {} +

通常のファイル-type fのみを検索します(通常のファイルを指す場合でもシンボリックリンクも除外します)。ディレクトリ以外の任意のタイプのファイルを検索する場合(ただし、fifosや/ dev / zeroなどのファイルのタイプがあることに注意してください)通常は読みたくない)、-type fGNU固有のものに置き換えます! -xtype d(シンボリックリンク解決後-xtype dのタイプがディレクトリのファイルに一致します)。

GNUの場合grep

grep -r pattern /the/dir

(ただし、GNU grepの最新バージョンをお持ちでない限り、ディレクトリに降りたときにシンボリックリンクをたどることに注意してください)。-D readオプションを追加しない限り、非正規ファイルは検索されません。grepただし、GNUの最近のバージョンでは、まだシンボリックリンク内を検索しません。

GNUの非常に古いバージョンはfind標準{} +構文をサポートしていませんでしたが、非標準を使用できます。

cd /the/dir &&
  find . -type f -print0 | xargs -r0 grep pattern

パフォーマンスはI / Oバウンドになりがちです。つまり、検索を実行する時間は、ストレージからすべてのデータを読み取るのに必要な時間です。

データが冗長ディスクアレイ上にある場合、一度に複数のファイルを読み取るとパフォーマンスが向上する可能性があります(そうでない場合は低下する可能性があります)。パフォーマンスがI / Oに制限されていない場合(たとえば、すべてのデータがキャッシュにあるため)、複数のCPUがある場合は、並行処理grepsも役立つ可能性があります。GNU xargs-Pオプションでそれを行うことができます。

たとえば、データが3つのドライブを備えたRAID1アレイ上にある場合、またはデータがキャッシュ内にあり、CPUが3つあり、時間に余裕がある場合:

cd /the/dir &&
  find . -type f -print0 | xargs -n1000 -r0P3 grep pattern

(ここでは、1000ファイルごとに-n1000新しいgrepファイルを生成するために使用します。最大3つまで同時に実行されます)。

ただし、の出力grepがリダイレクトgrepされる場合、3つのプロセスからのインターリーブが不適切に出力されることに注意してください。この場合、次のように実行できます。

find . -type f -print0 | stdbuf -oL xargs -n1000 -r0P3 grep pattern

(最新のGNUまたはFreeBSDシステムで)または--line-bufferedGNU のオプションを使用しますgrep

patternが固定文字列の場合、-Fオプションを追加すると問題が改善される可能性があります。

マルチバイト文字データでない場合、またはそのパターンのマッチングの場合、データがマルチバイト文字であるかどうかは関係ありません。

cd /the/dir &&
  LC_ALL=C grep -r pattern .

パフォーマンスを大幅に改善できます。

そのような検索を頻繁に行うことになった場合、そこにある多くの検索エンジンの1つを使用してデータのインデックスを作成することができます。


3

単一のディレクトリにある26000個のファイルは、ほとんどのファイルシステムにとって大量です。時間のかなりの部分がこの大きなディレクトリを読んでいる可能性があります。それぞれ数百個のファイルのみの小さなディレクトリに分割することを検討してください。

find間違ったやり方をしない限り、呼び出しはパフォーマンスの低下を説明できません。これは、ディレクトリを横断する高速な方法であり、長すぎるコマンドラインを実行しようとするリスクがないことを保証します。-exec grep PATTERN {} +コマンド呼び出しごとにできるだけ多くのファイルをパックするを使用し、ファイルごとに1 回-exec grep PATTERN {} \;実行するを使用しないようにしてください。ファイルごとに1回コマンドを実行grepすると、かなり遅くなります。


ありがとう あなたが書いているものを正確に作成しましたが、grepの3倍の時間が
かかりました...-user2778979

ジル、1つのディレクトリの26,000個のファイルと、たとえば100個のディレクトリに分散した26,000個のファイルのパフォーマンスが大幅に異なると言っているのですか?
user001

1
@ user001はい。それらの違いは、ファイルシステムと、場合によっては基礎となるストレージに依存しますが、単一のディレクトリの26000ファイルと比較して、100ディレクトリのそれぞれに260ファイルがあると、ファイルシステムがかなり高速になると思います。
ジル 'SO-悪であるのをやめる'

説明をありがとう。不一致の原因を理解するために、この点についてフォローアップの質問をしました。
user001

0

すべてのファイルを複数回grepする必要がある場合(あなたが言ったように、スクリプトを実行する)、RAMディスクを調べ、そこにすべてのファイルをコピーしてからファイルを複数回grepすることをお勧めします少なくとも100倍。

あなただけの十分なラムが必要です。それ以外の場合は、ファイルのインデックス作成を検討する必要があります。luceneまたはnosqlデータベースにアクセスし、クエリを実行します。


他の場所で述べたように、これは、実行するファイルが多すぎるという事実を助けませんgrep。「常に新しいファイルを作成するスクリプトがあるため、すべてのファイルを異なるディレクトリに配置することはできません。」という点もあります。
ジェフシャラー

-2

ディレクトリ内のすべてのファイル

grep 'search string' *

再帰的に

grep -R 'search string' *

-1を詳しく説明しますか?
マルクス

4
私はダウン投票しませんでしたが、あなたにはいくつかの問題があります:OPは「argリストが長すぎます」と言及しました。2番目の方法は、その点でも役に立ちません(あなたがの.代わりに使用した場合は助けになります*)。*ドットファイルを除外します(ただし、再帰ディレクトリ内のファイルではなく、-Rを使用します)。-rとは対照的に、-RはGNU grepの最新バージョンでもシンボリックリンクに従います。また、で始まる名前、現在のディレクトリ内のファイルに問題があるでしょう-
ステファンChazelas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.