Pipe find in grep -v

18

Ich versuche, alle Dateien zu finden, die von einem bestimmten Typ sind und keine bestimmte Zeichenfolge enthalten. Ich versuche, es zu tun, indem ich find auf grep -v leite

Beispiel:

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

Das scheint nicht zu funktionieren. Es scheint nur die Dateien zurückzugeben, die der Befehl find gefunden hat. Was ich versuche, ist im Grunde alle .java-Dateien zu finden, die einem bestimmten Dateinamen entsprechen (zB endet mit 'Pb' wie in SessionPb.java) und die kein 'erweitertes SomethingSomething' enthalten.

Mein Verdacht ist, dass ich es falsch mache. Wie sollte der Befehl stattdessen aussehen?

Hyangelo
quelle
Sie könnten hinzufügen, was Sie denken lässt, dass es nicht funktioniert hat. Vielleicht ist Ihr Grep-Ausdruck zu explizit? braucht ein '-i' für die Unterscheidung zwischen Groß- und Kleinschreibung? Siehe auch meine Antwort unten ...
Lornix

Antworten:

19

Hier gibt es keine Notwendigkeit xargs. Außerdem müssen Sie die Option grepwith -L(Dateien ohne Übereinstimmung) verwenden, da ansonsten der Dateiinhalt anstelle des Namens ausgegeben wird, wie in Ihrem Beispiel.

find . -type f -iname "*.java" -exec grep -L "something somethin" {} \+
eilen
quelle
1
-Lhat schon verhandlungen, weil es heißt files _without_ match. Daher brauchen Sie -vhier keine Option.
Ansturm
1
xargsist viel, viel besser als find+ -exec. Ersteres erstellt einen grepProzess, der alle Dateien als Argumente abruft, während letzteres grepfür jede Datei einmal ausgeführt wird.
krlmlr
3
nicht mit dem extra + am ende.
Lynxlynxlynx
5
@ user946850 -exec ... {} \+entspricht nicht xargs. Bitte lesen Sie die findutils Dokumentation! (Ich habe ziemlich hart daran gearbeitet!)
James Youngman
2
@ user946850 ja. Einer der Unterschiede besteht darin, dass (standardmäßig) xargsdie Eingabe verarbeitet und die Argumente in Leerzeichen getrennt werden. Anführungszeichen gelten auch speziell (standardmäßig) für xargs. Keines dieser Dinge ist wahr für -exec ... {} +. In alten Versionen wurde xargsder Unterstrich als EOF-Indikator verwendet, dies ist jedoch nicht mehr der Fall.
James Youngman
7

Du hast es wirklich fast geschafft ...

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

Der Punkt '.' sagt, von hier aus zu beginnen. (deins impliziert es .. aber nimm niemals an).

-iname verwendet die Suche ohne Berücksichtigung der Groß- und Kleinschreibung, nur für den Fall (oder nur für den Fall, dass dies nicht der Fall ist).
-print0 sendet Dateinamen mit einem nachgestellten \ x00-Zeichen an xargs, wodurch Probleme mit Dateinamen mit Leerzeichen vermieden werden.

Die '-0' in xargs gibt an, dass Dateinamen mit \ x00 anstelle von Rückgaben enden sollen.

und dein grep Befehl ...

So ziemlich alles verstanden.


BEARBEITEN::

Von Ihrem Update:

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

sollte helfen. (Hinzugefügt -L von @ Ansturm Antwort, gute Arbeit)

Ich habe die Idee, dass Ihr grep entweder die Option '-i' benötigt oder weniger explizit sein soll.

Versuchen Sie den Befehl in Teilen ... Gibt DIESE Dateinamen richtig aus?

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

Wenn ja, dann stimmt Ihr Problem wahrscheinlich entweder nicht mit Ihrem Suchmuster überein (Rechtschreibfehler? Es passiert!) Oder es gibt einfach keine Übereinstimmungen.

Absolut schlimmster Fall:

grep -riL "something" *

Ich werde viel mehr arbeiten, um alles zu durchsuchen, aber ich sollte Ihnen eine Ausgabe geben.

Lornix
quelle
Ich habe Ihre Änderungen ausprobiert und erhalte immer noch nicht das erwartete Ergebnis. Ich werde versuchen, die Frage zu aktualisieren, um sie klarer zu machen.
Hyangelo
Wenn der Autor der Frage nur nach Dateinamen suchen möchte, sollte das grep nicht 'grep -l -v' sein?
Bruce Ediger
Er sucht nach bestimmten Inhalten in den * .java-Dateien
Lornix
xargs -0 grep -v "something something"sein sollte , xargs -0 grep -v "something something" /dev/nullsonst werden Sie ungeradee Ergebnisse erhalten , wenn finde keine passenden Dateien erzeugt.
James Youngman
{Grinst} Ja, irgendwo da drin ist die Logik haarig geworden. Nichts ist vergleichbar mit einem umgekehrten Mehrfachtest mit falscher Logik, der Kopfschmerzen verursacht.
Lornix
4

Der Computer ist ein Computer: Er tut, was Sie ihm befohlen haben, anstatt das zu tun, was Sie von ihm wollten.

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

hello world
this is something something
something else

extends SomethingSomethingVerwenden Sie die folgende -LOption, um Dateien zu drucken, die nirgendwo enthalten :

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

Einige Versionen von grep verfügen nicht über die -LOption (sie wird von POSIX nicht angegeben ). Wenn dies nicht der Fall ist, lassen Sie es nichts drucken und den Rückkehrcode verwenden, damit die aufrufende Shell 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 einem anderen System mit GNU grep) müssen Sie es nicht verwenden find, da grepes sich um ein rekursives System handelt.

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

Wenn Ihre Shell ksh oder bash oder zsh ist, können Sie die Shell veranlassen, den Dateinamen abzugleichen. Bei Bash set -o globstarzuerst ausführen (Sie können dies in Ihre einfügen ~/.bashrc).

grep -L -E 'extends[[:space:]]+SomethingSomething' **/*.java
Gilles 'SO - hör auf böse zu sein'
quelle
Wow das ist noch besser. Ich habe 'extend (s) + SomethingSomething' verwendet, was meines Erachtens zu funktionieren schien. Gibt es bei dieser Syntax einen Unterschied zu der in der Extended RegEx-Version angegebenen?
Hyangelo
@Hyangelo \sist eine GNU grep Erweiterung, mit der ich gleichbedeutend bin [[:space:]].
Gilles 'SO- hör auf böse zu sein'