web-dev-qa-db-ja.com

grepを使用して、2つの文字列を含むディレクトリ内のすべてのファイルを検索します

私は、ファイル内の2つの文字列(各文字列の全体)をどこでも(相互に近接している必要はありません)見つけるための正しい構文を理解しようとしています。したがって、fooと番号321の両方を含むファイルは、単独である必要はなく、部分文字列でもかまいません。私は運が悪いのに以下を試しました:

grep 'foo\|321' *

grep 'foo|321'
24
imaginative

GNU grep

2番目のgrepはファイルのリストを操作する可能性があるため、少し高速になるはずです。

grep -lZ 'foo' * | xargs -0 grep -l '321'

検索付きPOSIX grep

findは、再帰ディレクトリを検索する場合に便利です(この場合、-mindepthおよび-maxdepthオプション。

find . -mindepth 1 -maxdepth 1 -type f -exec grep -q 'foo' {} \; -exec grep -l '321' {} +
21
kojiro

あなたは短いスクリプトでこれを行うことができます:

for FILE in *
do
  grep -q foo $FILE && grep -q 321 $FILE && echo $FILE
done

これを1行で行うこともできます。

for FILE in *; do grep -q foo $FILE && grep -q 321 $FILE && echo $FILE; done

grepは、文字列が見つかった場合は0(true)を返し、コマンドを&&で区切ると、最初のコマンドがtrueの場合にのみ2番目のコマンドが実行されます。 -qオプションは、grepが何も出力しないようにします。

エコーは、両方の文字列が同じファイルで見つかった場合にのみ実行されます。


別の方法を考えました。この方法は、問題のファイルがインストールしたRAMよりも大きい場合、各ファイルを1回だけgrepする必要があるため、より効率的です。

 for FILE in *
 do
   test $(egrep -o "foo|321" $FILE | uniq | sort | uniq | wc -l) -eq 2 && echo $FILE
 done

そして一行バージョン:

 for FILE in *; do test $(egrep -o "foo|321" $FILE | uniq | sort | uniq | wc -l) -eq 2 && echo $FILE; done
15
Ladadadada

奇妙な。私にとっては両方のバリアントが機能します(grep(GNU grep)2.13):

grep 'foo\|321'
grep -E 'foo|321'

編集1-両方が一致するファイルのみを表示

for file in *回答は機能しますが、パフォーマンスの悪夢になる可能性があります(大量のファイルの場合):ファイルごとに少なくとも2つのプロセス。これはより高速です(GNU世界では):

find . -type f -print0 | xargs -0 -r grep --files-with-matches --null -- string1 |
  xargs -0 -r grep --files-with-matches -- string2

string1は、一致が少なくなるものでなければなりません。

2
Hauke Laging

基本的に、ディレクトリ内の特定の文字列を含むすべてのファイルを検索するには、次を使用できます。

grep -lir "pattern" /path/to/the/dir
  • -l:このスキャンを行うには、最初の一致で停止します
  • -i:パターンと入力ファイルの両方で大文字と小文字の区別を無視します
  • -r:ディレクトリの下のすべてのファイルを再帰的に検索します

2つのパターンを検索するには、次のことを試してください。

grep -lr "321" $(grep -lr "foo" /path/to/the/dir)
2
quanta