grep、awk、またはsedを使用して、あるパターンと一致しますが、他のパターンと一致しないファイルを見つけます。

grep、awk、またはsedを使用して、あるパターンと一致しますが、他のパターンと一致しないファイルを見つけます。

1つの文字列(例:)を含まないが別の文字列(例:)を含むファイルを見つける必要があります.php.plaaabbb

現在、次のコマンドを使用しています。

find /path/ \( -iname '*.php*' -or -name '*.pl*' \) -exec sh -c 'grep -l -v "aaa" {} | grep -l "bbb" {}' \; > resulttofile

検索するファイルが50万個ほどあるのに知りたいです。

  • 私のコマンドが正しく機能したら、目のサンプリングを介して肯定的な結果を得ることができます。
  • 他の形式(現在の仮想マシンでは約2分かかりますが、より多くのファイルが追加される予定)を使用するか、代わりにまたは両方を組み合わせて使用​​する方が速いawk場合。sedgrepgrep

システムはDebian GNU/Linuxです。

答え1

あなたのコマンドは機能しません。最初のコマンドはgrep一致しない行を含むすべてのファイルを一覧表示し、2番目のコマンドは処理する"aaa"独自のファイルを提供するため、最初のコマンドの出力を無視します。したがって、どうかどうかに関係なくgrep一致するファイルのリストを取得します。"bbb"それらは含まれています"aaa"。行一致()grepがない場合にのみファイルを一覧表示するように要求し、結果ファイルのリストを処理して2番目のファイルにのみ供給する必要があります(または2番目のファイルが最初のファイルで始まるようにする必要があります)。"aaa"grep -Lxargsgrepgrep

結論は、findリストされたファイル名がシェルに問題を引き起こさない場合にのみ機能することです。{}特定のコマンドに直接含めると、sh -cファイル名は最終的にシェルコマンドとして解釈されます(参照「find -exec sh -c」を使っても安全ですか?詳細はこちら)。

GNUを使用すると仮定すると、以下は少ないgrep呼び出しが必要で、より安全です。grep

find /path/ \( -iname '*.php*' -o -name '*.pl*' \) -exec grep -LZ aaa {} + |
  xargs -r0 grep -l bbb

これ-or演算子はGNU拡張ですfind。使用-o携帯性のため。

答え2

テストされていませんが、GNU awkを使用して必要に応じて動作しますnextfileENDFILE

find /path/ \( -iname '*.php*' -or -name '*.pl*' \) -exec awk '
    /aaa/{a=1} /bbb/{b=1} a&&b{nextfile} ENDFILE{if (b && !a) print FILENAME; a=b=0}
' {} + > resulttofile

上記は複数のファイルに対して一度だけawkを呼び出すので、効率的です。

上記は通常、ファイルの複数のパターンを一致させ、ファイルを完全に読み取った後に一致した組み合わせの結果を評価する方法ですが、次のようになります。@G-Manは「モニカ復元」と言います。で言及コメントaaaこの特定のケースでは成功基準がaaa存在しないため、一致するエントリから現在のファイルの読み取りを停止して効率を向上させることができます。

/aaa/{a=1; nextfile} /bbb/{b=1} ENDFILE{if (b && !a) print FILENAME; a=b=0}

答え3

findコマンドを使用して、複数の-execディレクティブ(または他のディレクティブ)を連結できます。

find /path \( -iname '*.php*' -or -name '*.pl*' \) -exec grep -q "bbb" {} ";" \
     -exec grep -L "aaa" {} ";" > resulttofile

(改行はSEのレイアウトに合わせるためのものです)。

関連情報