Finde über die Pipe nach grep -v

Finde über die Pipe nach grep -v

Ich versuche, alle Dateien zu finden, die von einem bestimmten Typ sind und eine bestimmte Zeichenfolge nicht enthalten. Ich versuche, dies zu erreichen, indem ich find an grep -v weiterleite.

Beispiel:

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

Das scheint nicht zu funktionieren. Es scheint nur alle Dateien zurückzugeben, die der Find-Befehl gefunden hat. Ich versuche im Grunde, alle .java-Dateien zu finden, die einem bestimmten Dateinamen entsprechen (z. B. mit „Pb“ enden wie in SessionPb.java) und die kein „extends SomethingSomething“ enthalten.

Ich vermute, dass ich es falsch mache. Wie sollte der Befehl stattdessen aussehen?

Antwort1

Das ist hier nicht nötig xargs. Sie müssen auch die Option (Dateien ohne Übereinstimmung) verwenden grep, -Lda sonst der Dateiinhalt statt des Namens ausgegeben wird, wie in Ihrem Beispiel.

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

Antwort2

Du hast es wirklich fast verstanden ...

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

Der Punkt „.“ bedeutet, dass Sie hier beginnen sollen. (Ihre Aussage impliziert dies, aber gehen Sie nie davon aus.)

-inameverwendet eine Groß-/Kleinschreibung-unabhängige Suche, nur für den Fall (oder einfach in keinem Fall).
-drucken0sendet Dateinamen mit einem abschließenden \x00-Zeichen an xargs, wodurch Probleme mit Dateinamen, die Leerzeichen enthalten, vermieden werden.

Das „-0“ bei xargs bedeutet, dass Dateinamen erwartet werden, die mit \x00 enden, anstatt dass etwas zurückgegeben wird.

und Ihr Grep-Befehl ...

So ziemlich verstanden.


BEARBEITEN::

Aus Ihrem Update:

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

sollte helfen. (-L aus @rushs Antwort hinzugefügt, gute Arbeit)

Ich habe den Eindruck, dass Ihr grep entweder die Option „-i“ oder eine weniger explizite Angabe benötigt.

Probieren Sie den Befehl in Teilen aus. Gibt DIES Dateinamen aus, die richtig erscheinen?

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

Wenn ja, liegt Ihr Problem wahrscheinlich darin, dass entweder Ihr Grep-Suchmuster nicht übereinstimmt (Rechtschreibfehler? Das kommt vor!) oder dass es einfach keine Übereinstimmungen gibt.

Absoluter Worst-Case:

grep -riL "something" *

wird VIEL mehr Arbeit machen, alles zu durchsuchen, sollte Ihnen aber einige Ergebnisse liefern.

Antwort3

Der Computer ist ein Computer: Er tut, was Sie ihm gesagt haben, statt, was Sie von ihm wollen.

grep -v "something something"druckt alle Zeilen, die nicht enthalten something something. Beispielsweise druckt es zwei der folgenden drei Zeilen:

hello world
this is something something
something else

Um Dateien zu drucken, die nirgendwo etwas enthalten extends SomethingSomething, verwenden Sie die -LOption:

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

Einige Versionen von grep haben diese Option nicht -L(sie wird nicht angegeben durchPOSIX). Wenn dies bei Ihnen nicht der Fall ist, lassen Sie nichts drucken und verwenden Sie den Rückgabecode, damit die aufrufende Shell stattdessen das tut, was sie tun soll.

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

Alternativ können Sie awk verwenden.

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 }
'

Unter Linux oder Cygwin (oder anderen Systemen mit GNU grep) müssen Sie nicht verwenden find, da greprekursiv sein kann.

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

Wenn Ihre Shell KSH, Bash oder ZSH ist, können Sie die Dateinamenübereinstimmung von der Shell durchführen lassen. Führen Sie unter Bash set -o globstarzuerst aus (Sie können dies in Ihrem einfügen ~/.bashrc).

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

Antwort4

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

was Sie „herauslesen“, wird auf stderr und nicht auf stdout angezeigt.

der obige Befehl leitet stderr auf stdout um

Quelle

verwandte Informationen