ある文字列があり、特に別の文字列がないファイルのリストを再帰的に表示するにはどうすればよいですか?また、ファイル名ではなくファイルのテキストを評価することを意味します。
結論:
コメントごとに、私は最終的に使用しました:
find . -name "*.html" -exec grep -lR 'base\-maps' {} \; | xargs grep -L 'base\-maps\-bot'
これにより、「base-maps-bot」ではなく「base-maps」でファイルが返されました。ありがとうございました!!
これを試して:
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>
が含まれていない場合にのみファイル名を出力します。
上記の回答で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
の方が高速です。各ファイルの個別のgrep
プロセスではなく、1つのgrep
プロセスを使用してすべてのファイルの最初のフィルターを実行するためです。
これらの答えは一致するように見えます[〜#〜] both [〜#〜]文字列。次のコマンドはより適切に動作するはずです。
grep -l <string-to-match> * | xargs grep -c <string-not-to-match> | grep '\:0'
より一般的な構成を次に示します。
find . -name <nameFilter> -print0 | xargs -0 grep -Z -l <patternYes> | xargs -0 grep -L <patternNo>
このコマンドは、<nameFilter>
を含むが<patternYes>
を含まない<patternNo>
(必要に応じてfind
述語を調整)と名前が一致するファイルを出力します。
機能強化は次のとおりです。
名前でフィルタリングする必要がない場合(多くの場合、現在のディレクトリ内のすべてのファイルを考慮したい場合)、find
を削除し、最初のgrep
に-R
を追加できます。
grep -R -Z -l <patternYes> | xargs -0 grep -L <patternNo>
見つける。 -maxdepth 1 -name "* .py" -exec grep -L "string-not-to-match" {} \;
このコマンドは、同じディレクトリに「string-not-to-match」を含まないすべての「.py」ファイルを取得します。