Cca 26 000ファイルのディレクトリがあり、これらすべてのファイルをgrepする必要があります。問題は、できる限り速くそれを必要とすることです。そのため、grepがfindコマンドから1つのファイルの名前を取得し、一致をファイルに書き込むスクリプトを作成することは理想的ではありません。 「引数リストが長すぎる」問題が発生する前に、このすべてのファイルをgrepするのにcca 2分かかりました。それを行う方法のアイデアはありますか?編集:常に新しいファイルを作成するスクリプトがあるため、すべてのファイルを異なるディレクトリに配置することはできません。
find
の場合:
cd /the/dir
find . -type f -exec grep pattern {} +
(-type f
はregularファイルのみを検索します(通常のファイルを指す場合でもシンボリックリンクも除外します。)ディレクトリ以外の任意のタイプのファイルを検索する場合(ただし、いくつかのタイプのファイルがあることに注意してください)通常は読みたくない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
も役立つ可能性があります。 GNU xargs
の-P
オプションでそれを行うことができます。
たとえば、データが3つのドライブを持つRAID1アレイ上にある場合、またはデータがキャッシュ内にあり、時間に余裕のある3つのCPUがある場合:
cd /the/dir &&
find . -type f -print0 | xargs -n1000 -r0P3 grep pattern
(ここでは、-n1000
を使用して、1000ファイルごとに新しいgrep
を生成します。一度に3つまで並列で実行されます)。
ただし、grep
の出力がリダイレクトされる場合は、3つのgrep
プロセスからの出力が正しくインターリーブされないことに注意してください。この場合、次のように実行できます。
find . -type f -print0 | stdbuf -oL xargs -n1000 -r0P3 grep pattern
(最近のGNUまたはFreeBSDシステム)またはGNU grep
の--line-buffered
オプションを使用します。
pattern
が固定文字列の場合、-F
オプションを追加すると問題が改善する可能性があります。
マルチバイト文字データでない場合、またはそのパターンのマッチングの場合、データがマルチバイト文字かどうかは関係ありません。
cd /the/dir &&
LC_ALL=C grep -r pattern .
パフォーマンスを大幅に向上させることができます。
このような検索を頻繁に行う場合は、そこにある多くの検索エンジンの1つを使用してデータにインデックスを付けることができます。
単一のディレクトリにある26000個のファイルは、ほとんどのファイルシステムにとって大量です。時間のかなりの部分がこの大きなディレクトリの読み取りに費やされている可能性があります。それを数百のファイルだけの小さなディレクトリに分割することを検討してください。
find
を呼び出しても、間違っていない限り、パフォーマンスの低下を説明できません。これは、ディレクトリをトラバースする高速な方法であり、長すぎるコマンドラインを実行しようとするリスクを冒さないようにするためです。コマンドの呼び出しごとにできるだけ多くのファイルをパックする-exec grep PATTERN {} +
を使用してください。ファイルごとにgrep
を1回実行する-exec grep PATTERN {} \;
は使用しないでください。ファイルごとに1回コマンドを実行するのはかなり遅くなる可能性があります。
すべてのファイルを複数回grepする必要がある場合(前述のように、スクリプトを実行します)、ramディスクを調べ、そこにすべてのファイルをコピーしてから、ファイルを複数回grepすることをお勧めします。これにより、検索が高速化されます。少なくとも100倍。
十分なRAMが必要です。それ以外の場合は、ファイルのインデックス作成を検討する必要があります。 luceneまたはnosqlデータベースに入れてから、クエリを実行します。