150,000を超えるファイルを含むディレクトリがあります。テキスト変数にテキストが格納されているすべてのファイルリストを作成し、そのファイルリストを別の変数に保存したいと思います。
私はまず次のことを試してみます。
searchtext="Subject: Your"
files = $(grep "$searchtext" ./* | awk '{print ($1)}' )
、この方法はディレクトリ内の適切な数のファイルに対して機能しますが、150,000個のファイルを含むディレクトリで実行すると、「パラメータリストが長すぎます」というエラーが生成されます。 (Awk with printは、grep結果からファイル名のみを抽出するために使用されます。)
files=$(grep "$searchtext" ./* | awk '{print ($1)}') は 150K ファイルディレクトリで動作しますが、実行にはほぼ 90 分かかることがわかりました。
ファイルにある場合、$ searchtext文字列はファイルの先頭にあります。それで、grepがテキストの最初の30行だけを表示するように制限すると、作業速度を大幅に向上させることができると思いました。どうすればいいかわかりません。ディレクトリ内の各ファイルの最初の50行をどのように再帰的にgrepしますか?そこでいくつかの提案を試しました。私の仕事に最適なものは次のとおりです。
searchtext="Subject: Your"
find . -type f -exec head -n 30 {} + | grep "$searchtext"
これは許可された時間内に実行されますが、検索テキストを含むファイルのファイル名を出力しません。 grep -lを試しましたが、「find:head' terminated by signal 13 ". Somewhere it was suggested that the using "\" instead of "+" might be more appropriate. However, that also generates an error: "find: missing argument to
-exec」というエラーが発生しました。
ファイル名を含むgrepの結果を調べるときに別の問題が発生すると予想しました。 grep出力を変数に割り当てようとすると、次のようになります。
files = $(find . -type f -exec head -n 30 {} + | grep "$searchtext")
「ut1.sh:行16:ファイル:コマンドが見つかりません」というエラーが発生します。何らかの理由で "files"変数はコマンドとして解釈されますか?私のスクリプト名はut1.shです。以前は、問題なく何度もこのように変数を割り当てました。
私のbashバージョンはGNU bash、バージョン4.1.2(2)-release(x86_64-redhat-linux-gnu)です。
どのように完了し、私の試みにどのような問題がありますか?
ありがとう
ベストアンサー1
一致するファイル名のリストを取得するには、スイッチを使用して出力を処理せずにファイル名のみを取得grep
できます。一致するファイルの場合は、パターンを一度見つけて停止できるため、速度も速くなります。-l
awk
grep
grep -le "$searchtext" ./*
単純な割り当てでは、出力を変数に入れることができます(ただし、スペースとワイルドカードを含むファイル名は問題を引き起こす可能性があります)。
files=$(grep -le "$searchtext" ./* )
これに関しては:
find . -type f -exec head -n 30 {} + | grep "$searchtext"
ここのパイプはfind
と を区別するgrep
ので、各ファイルの最初の30行を効果的に連結してから(ここでファイル名を追跡できない)、結果をgrepします。grep -l
入力全体に一致するものがあるかどうかだけを通知できます。find
各ファイルの合計を個別に結合するhead
には、内部でシェルを実行する必要がありますgrep
。
export searchtext
find . -type f -exec sh -c 'head -n 30 "$1" | grep -q "$searchtext" && echo "$1"' sh {} \;
しかし、私たちもawk
そうすることができます。これにより、最初の30行(GNU awk)でのみパターンを見つけることができます。
awk -vpattern="$searchtext" 'FNR <= 30 && $0 ~ pattern { print FILENAME; nextfile }' *
または検索を使用してください。
find . -type f -exec awk -vpattern="$searchtext" 'FNR <= 4 && $0 ~ pattern { print FILENAME; nextfile }' {} +