約 500 個の文字列があり、ディレクトリ内でそれらを含むファイルを検索し、文字列を含むファイル名を取得したいと考えています。これまでは、次のものを使用してきました。
find -name 'LYFNRE.*' -exec grep -f file1.txt {} \; -print
しかし、問題は、文字列が多数のファイルで見つかるため、出力が膨大であるため、どの文字列が存在し、どの文字列が欠落しているかを見つけるのが難しいことです。見つかった場所に対応するファイル名とともに文字列を印刷するのを手伝っていただけますか。
答え1
grep
ファイル名だけを指定すればいいのです。GNU ではgrep
次のようにできます:
grep -HFf ../strings.txt *
次のような出力が表示されます。
[filename]:[matched_line]
...ディレクトリ内のすべてのファイルのすべての一致に対して。行番号も取得できます。
grep -HnFf ../strings.txt *
...これにより...
[filename]:[line_number]:[matched_line]
答え2
問題は、一度に 1 つのファイルを に渡していることですgrep
。 がgrep
コマンド ラインで 1 つのファイルを見つけると、検索場所を正確に知っているものと想定されるため、一致の前にファイル名が表示されません。
常にファイル名を出力するように強制するコツは、(一致するものがない)grep
も渡すことです。一部の grep 実装には、そのためのオプションがあります: 。/dev/null
-H
さらに、の-exec … {} +
代わりに を使用すると、-exec … {} \;
一度に多数のファイルに対してプログラムを実行できます。この方が高速です。ただし、 または を渡す必要があります。一致するファイルが 1 つしかない場合や、 を複数回呼び出す必要がある一致が多数あり、そのうち1 回がたまたま 1 つのファイルに関係する場合など、コマンドが 1 つのファイルに対してのみ呼び出される可能性があるためです。/dev/null
-H
grep
find -name 'LYFNRE.*' -exec grep -f file1.txt /dev/null {} +
grep
GNU grep および最近の BSD 実装 (OSX を含む) は、を必要とせずに再帰的に呼び出すオプションをサポートしていますfind
。
grep -R --include='LYFNRE.*' -f file1.txt -H .
あるいは、シェルで再帰的なグロブを行うこともできます。zsh では、これはそのままで動作します。bash では、shopt -s globstar
最初に を実行する必要があり、bash はディレクトリへのシンボリック リンクを再帰的に実行することに注意してください ( find
zsh とは異なります)。
grep -f file1.txt /dev/null **/LYFNRE.*
答え3
egrep を使用します:
egrep -n "str1|str2|str3" file_names
-n は文字列が見つかった特定のファイルの行番号を出力します