web-dev-qa-db-ja.com

ディレクトリ内の複数のファイルで複数の文字列を検索し、文字列とそれが見つかった対応するファイル名を出力する

約500個の文字列があり、それらを含むファイルをディレクトリ内で検索して、文字列を含むファイル名を取得します。これまでのところ、私は使用しています:

find -name 'LYFNRE.*' -exec grep -f file1.txt {} \; -print

しかし問題は、文字列が多くのファイルで見つかる可能性があるため、膨大な出力のために、どの文字列が存在し、どの文字列が欠落しているかを見つけるのが難しいことです。文字列が見つかった場所の対応するファイル名で文字列を印刷するのを手伝ってくれませんか。

2
Jay

grepにファイル名を渡させるだけです。 GNU grepはこれを行うことができます:

grep -HFf ../strings.txt *

次のような出力が表示されます。

[filename]:[matched_line]

...ディレクトリ内のすべてのファイルのすべての一致について。行番号も取得できます。

grep -HnFf ../strings.txt *

...提供する...

[filename]:[line_number]:[matched_line]
2
mikeserv

問題は、一度に1つのファイルをgrepに渡すことです。 grepがコマンドラインで単一のファイルを見つけた場合、検索する場所が正確にわかっていると想定しているため、一致の前にファイル名は表示されません。

grepが常にファイル名を出力するように強制するコツは、/dev/nullも渡すことです(一致するものはありません)。一部のgrep実装には、そのためのオプションがあります:-H

さらに、-exec … {} +の代わりに-exec … {} \;を使用して、一度に多くのファイルに対してプログラムを実行できます。これはより高速です。 /dev/nullまたは-Hを渡す必要があります。一致するファイルが1つあるため、またはgrepが数回呼び出され、1回は単一のファイルに関係しています。

find -name 'LYFNRE.*' -exec grep -f file1.txt /dev/null {} +

GNU grepおよび最近のBSD実装(OSXを含む)は、grepを必要とせずにfindを再帰的に呼び出すオプションをサポートしています。

grep -R --include='LYFNRE.*' -f file1.txt -H .

または、シェルで再帰的グロビングを行うこともできます。 zshでは、これはそのまま使用できます。 bashでは、最初にshopt -s globstarを実行する必要があります。また、bashがディレクトリへのシンボリックリンクを介して再帰することに注意してください(findやzshとは異なります)。

grep -f file1.txt /dev/null **/LYFNRE.*

egrepを使用:

egrep -n "str1|str2|str3" file_names

-nは、文字列が見つかった特定のファイルの行番号を出力します

0
csny