find を grep -v にパイプする

find を grep -v にパイプする

特定のタイプで特定の文字列を含まないすべてのファイルを検索しようとしています。findをgrep -vにパイプすることでこれを実行しようとしています。

例:

find -type f -name '*.java' | xargs grep -v "something something"

これはうまくいかないようです。find コマンドが見つけたすべてのファイルを返すだけのようです。私がやろうとしているのは、基本的に、特定のファイル名に一致し (たとえば、SessionPb.java のように 'Pb' で終わる)、内部に 'extends SomethingSomething' が含まれないすべての .java ファイルを見つけることです。

私のやり方が間違っているのではないかと思います。では、代わりにコマンドはどのようになるのでしょうか?

答え1

ここでは必要ありません。また、オプション(一致しないファイル)xargsを使用する必要もあります。そうしないと、例のように、名前ではなくファイルの内容が出力されます。grep-L

find . -type f -iname "*.java" -exec grep -L "something somethin" {} \+

答え2

ほぼ正解です...

find . -type f -iname "*.java" -print0 | xargs -0 grep -v "something something"

ドット「.」はここから始めることを示しています。(あなたの場合はそれが暗示されていますが、決して想定しないでください)。

-イネーム念のため、大文字と小文字を区別しない検索を使用します (または大文字と小文字を区別しない検索を使用します)。
-印刷0末尾に \x00 文字を付けてファイル名を xargs に送信します。これにより、ファイル名にスペースが含まれる場合に発生する問題を回避できます。

xargs の '-0' は、ファイル名が改行ではなく \x00 で終わることを期待することを示します。

そして grep コマンド...

ほぼ分かりました。


編集::

あなたのアップデートから:

find . -type f -iname "*pb.java" -print0 | xargs -0 grep -iL "something"

役に立つはずです。(@rush の回答から -L を追加しました。よくできました)

grep には '-i' オプションが必要であるか、または明示的でない必要があると思われます。

コマンドを部分的に試してください...これにより、適切と思われるファイル名が出力されますか?

find . -type f -iname "*pb.java"

もしそうなら、問題はおそらく grep 検索パターンが一致していない (スペルミス? よくあることです!) か、一致するものがまったくないことです。

最悪のケース:

grep -riL "something" *

すべてを検索するにはさらに多くの作業が必要ですが、何らかの出力が得られるはずです。

答え3

コンピュータはコンピュータらしく、あなたが望んだことではなく、あなたが指示したことを実行します。

grep -v "something something"を含まないすべての行を出力しますsomething something。たとえば、次の 3 行のうち 2 行を出力します。

hello world
this is something something
something else

どこにも含まれていないファイルを印刷するにはextends SomethingSomething、次の-Lオプションを使用します。

grep -L -E 'extends[[:space:]]+SomethingSomething' FILENAME…

grepのバージョン-Lによっては、このオプションがありません(POSIX)。そうでない場合は、何も印刷せず、戻りコードを使用して、呼び出し元のシェルが代わりに実行すべきことを実行するようにします。

grep -q -E 'extends[[:space:]]+SomethingSomething' FILENAME ||
echo "$FILENAME"

あるいは、awk を使用します。

awk '
    FNR == 1 && NR != 1 && !found { print fn }
    FNR == 1 { fn = FILENAME; found = 0; }
    /extends[[:space:]]+SomethingSomething/ { found = 1 }
    END { if (fn != "" && !found) print fn }
'

Linux または Cygwin (または GNU grep を備えた他のシステム) では、再帰が可能なので をfind使用する必要はありません。grep

grep -R --include='*.java' -L -E 'extends[[:space:]]+SomethingSomething'

シェルが ksh または bash または zsh の場合、シェルにファイル名のマッチングを行わせることができます。bash では、set -o globstar最初に を実行します (これを に記述できます~/.bashrc)。

grep -L -E 'extends[[:space:]]+SomethingSomething' **/*.java

答え4

find -type f -name '*.java' 2>&1 | grep -v "something something"

「grep 出力」している内容は、stdout ではなく stderr に表示されます。

上記のコマンドはstderrをstdoutにリダイレクトします

ソース

関連情報