私のディレクトリには26,000個のファイルがあり、すべてのファイルをgrepする必要があります。問題はできるだけ早くインポートする必要があるため、findコマンドからファイル名を取得し、一致をファイルに書き込むgrepスクリプトを作成するのは理想的ではありません。 「パラメータリストが多すぎる」問題が発生する前に、これらのファイルをすべて収集するのに約2分かかりました。どうすればいいのアイデアはありますか?編集:新しいファイルを生成し続けるスクリプトがあるため、すべてのファイルを別のディレクトリに配置することは不可能です。
答え1
そしてfind
:
cd /the/dir
find . -type f -exec grep pattern {} +
(-type f
検索専用です。定期的なファイル(通常のファイルを指してもシンボリックリンクではありません)。ディレクトリを除くすべての種類のファイルを検索する場合(ただし、fifosや/dev/zeroなどの一部のファイルタイプは通常読みたくありません)、-type f
GNU固有のファイルに置き換えます! -xtype d
(-xtype d
次のファイルと一致)。タイプ目次シンボリックリンク解決後))。
GNUの使用grep
:
grep -r pattern /the/dir
(ただし、最新バージョンのGNU grepがない場合は、ディレクトリに入るときにシンボリックリンクに従う必要があります。)オプションを追加しないと、珍しいファイルは検索されません-D read
。ただし、最新バージョンのGNUはgrep
まだシンボリックリンク内で検索されません。
非常に古いバージョンのGNUはfind
標準構文をサポートしていませんが、非{} +
標準構文を使用できます。
cd /the/dir &&
find . -type f -print0 | xargs -r0 grep pattern
パフォーマンスによっては、I/O が制限される場合があります。つまり、検索を実行するのにかかる時間は、リポジトリ内のすべてのデータを読み取るのにかかる時間です。
データが冗長ディスクアレイにある場合は、複数のファイルを同時に読み取るとパフォーマンスが向上する可能性があります(そうしないとパフォーマンスが低下する可能性があります)。並行性は、パフォーマンスがI / Oバインドされていない(たとえば、すべてのデータがキャッシュにあるため)、CPUが複数ある場合にもgreps
役立ちます。 GNUxargs
のオプションを使用して-P
これを行うことができます。
たとえば、データが3つのドライブを持つRAID1アレイにある場合、またはデータがキャッシュにあり、3つのCPUがアイドル状態の場合:
cd /the/dir &&
find . -type f -print0 | xargs -n1000 -r0P3 grep pattern
(ここでは、1000ファイルごとに-n1000
新しいファイルを作成し、grep
一度に最大3つのファイルを並列に実行するために使用されました。)
ただし、出力grep
がリダイレクトされると、3つのプロセスで重大にインターリーブされた出力が生成されますgrep
。この場合、次のように実行できます。
find . -type f -print0 | stdbuf -oL xargs -n1000 -r0P3 grep pattern
(最近のGNUまたはFreeBSDシステムで)または--line-buffered
GNUオプションを使用してくださいgrep
。
pattern
固定文字列の場合、このオプションを追加すると-F
問題が改善する可能性があります。
マルチバイト文字データでない場合、またはパターンマッチングのためにデータがマルチバイト文字であるかどうかが重要でない場合は、次のようにします。
cd /the/dir &&
LC_ALL=C grep -r pattern .
パフォーマンスを大幅に向上させることができます。
この種の検索を頻繁に実行すると、多くの検索エンジンのいずれかを使用してデータをインデックス化できます。
答え2
ほとんどのファイルシステムでは、単一のディレクトリに26,000個のファイルがある場合は大量です。この大きな目次を読むにはかなりの時間がかかることがあります。それぞれ数百のファイルのみを含む小さなディレクトリに分割することを検討してください。
find
間違っていない場合は、電話をかけてもパフォーマンスの低下は説明されません。これはディレクトリをブラウズする簡単な方法で、長すぎるコマンドラインを実行しようとする危険がないことを保証します。ファイルごとに一度実行する-exec grep PATTERN {} +
のではなく、各コマンド呼び出しでできるだけ多くのファイルを圧縮することを使用してください。ファイルごとに一度コマンドを実行すると、著しく遅くなる可能性があります。-exec grep PATTERN {} \;
grep
答え3
すべてのファイルを何度もgrepする必要がある場合(あなたが言ったようにスクリプトを実行する)、RAMディスクを見て、すべてのファイルをそこにコピーしてからファイルを何度もgrepすると、検索が速くなります。少なくとも100回。
十分なメモリーが必要です。それ以外の場合は、ファイルの索引付けを検討する必要があります。 lucene または nosql データベースに移動し、それに対してクエリを実行します。
答え4
ディレクトリ内のすべてのファイル
grep 'search string' *
再帰的
grep -R 'search string' *