上記の回答で xargs を使用する必要はありません。次のように同じことを達成できます:
find . -type f -exec grep -q <string-to-match> {} \; -not -exec grep -q <string-not-to-match> {} \; -print
grep -q 静かに実行するが、一致が見つかったかどうかを示す終了コードを返すことを意味します。 find 次に、その終了コードを使用して、残りのオプションを実行し続けるかどうかを決定できます。 -exec grep -q <string-to-match> {} \; の場合 0 を返し、次に -not -exec grep -q <string-not-to-match>{} \; を実行します .それも 0 を返す場合、-print を実行します。 、ファイルの名前を出力します。
find を使用して、別の回答が指摘したように この方法では、grep -Rl よりも大きな利点があります 特定のタイプのファイルのみを検索したい場合。一方、本当にすべてのファイルを検索したい場合は、 grep -Rl 1 つの grep を使用するため、おそらくより高速です。 個別の grep の代わりに、すべてのファイルに対して最初のフィルターを実行するプロセス ファイルごとに処理します。
これを試してください:
grep -rl <string-to-match> | xargs grep -L <string-not-to-match>
説明:grep -lr grep を再帰的に (r) <string-to-match> を含むすべてのファイルのリスト (l) を出力します。 . xargs はこれらのファイルをループし、grep -L を呼び出します。 それらのそれぞれに。 grep -L ファイルに <string-not-to-match> が含まれていない場合にのみファイル名を出力します .
これらの答えは 両方 一致していないようです 文字列。次のコマンドはより適切に機能するはずです:
grep -l <string-to-match> * | xargs grep -c <string-not-to-match> | grep '\:0'