Maildirディレクトリに500個のファイルをgrepしたいと思います。私は命令を出す。
grep MyPattern *
エラーメッセージが表示されます。
bash: /usr/bin/grep: Argument list too long
そのため、ファイルのリストをMyFilesファイルに保存し、次のコマンドを実行します。
for i in $(`cat MyFiles`); do echo $i; done
grepを実行する前にエコーを実行して確認したいと思います。ただし、これにより次のエラーが発生します。
bash: 1434361691.M617282P6399V0000000000000808I00000000000E16C1_23.ananda-linux,S=10055:2,S: command not found
ここで、1434...はディレクトリの最初のファイルです。
では元の質問に戻ります。メールボックス内のこれらすべてのファイルを見つけるためにgrepする方法。 50,000以上の電子メールを含むより大きなメールボックスがあります。
答え1
grep
現在のディレクトリで繰り返しファイルリストを整理してみてください。
grep -r MyPattern .
これはサブディレクトリから検索するため、まったく同じではありませんが、*
メールディレクトリの場合は通常必要なものです。
答え2
シェルが外部コマンドを実行するとき、コマンドラインはファイル名ワイルドカードパターン(たとえば)を拡張した後に特定の長さを*
超えてはいけません。
あなたの場合、grep 'PATTERN' *
拡張はシェルが実行するには長すぎるコマンドです。
2番目の例では:
for i in $(`cat MyFiles`); do echo $i; done
に保存されているファイル名を繰り返しようとしましたが、MyFiles
構文が非常に間違っています。
$(`cat MyFiles`)
同じですか?
$( $(cat MyFiles) )
これは、内容がMyFiles
コマンドとして解釈されることを意味します。これがcommand not found
エラーが発生する理由です。
この問題を解決する方法はさまざまですが、ファイルの内容を繰り返すのは良いアプローチではありません。
Stephenは素晴らしいソリューションを提供しました。彼の答えに、もう1つは、現在の作業ディレクトリがMaildirフォルダであると仮定することです。
find . -type f -exec grep 'PATTERN' {} +
これは、grep
大規模ファイルの配置に対して複数回実行されます。できるだけ。
これは次のようになります。
printf '%s\n' * | xargs grep 'PATTERN'
ただし、このfind
コマンドはスペースと改行を含むファイル名を処理します。
ここのコマンドは、printf
1行に1つのファイル名を出力します。grep 'PATTERN' *
ほとんどの場合と同じ問題は発生しません。組み込みコマンドなので、シェルから外部コマンドとして実行する必要はありません。
cat
ループソリューションも機能しますが、ループ出力の代わりに単に次のことができます。
for name in *; do
grep 'PATTERN' "$name"
done
これは次のように仮定します。一般ファイルのみ現在のディレクトリにあります。
メールメッセージのみを処理するには、次のものを使用できます。
for name in *,*; do
grep 'PATTERN' "$name" /dev/null
done
これは、1つ以上のカンマを含む名前を繰り返します。また、指定されたパターンに一致するファイル名を/dev/null
強制的に出力するように追加しました。grep
サポートしている場合は、代わりに/dev/null
削除して使用できます-H
。grep
grep
これらのループは、grep
ディレクトリ内の各ファイルに対して一度だけ実行されるため、遅くなります。