Wie kann ich alle Dateien finden, die KEINE Textzeichenfolge enthalten?

40

Welchen präzisen Befehl kann ich verwenden, um alle Dateien zu finden, die KEINE Textzeichenfolge enthalten?

Ich habe dies (mit -v, um die grep-Parameter zu invertieren) ohne Erfolg versucht:

find . -exec grep -v -l shared.php {} \;

Jemand sagte, das würde funktionieren:

find . ! -exec grep -l shared.php {} \;

Aber es scheint bei mir nicht zu funktionieren.

Diese Seite hat dieses Beispiel:

find ./logs -size +1c  > t._tmp
while read filename
do
     grep -q "Process Complete" $filename
     if [ $? -ne 0 ] ; then
             echo $filename
     fi
done < t._tmp
rm -f t_tmp

Aber das ist umständlich und überhaupt nicht prägnant.

ps: Ich weiß, dass grep -L *dies der Fall sein wird, aber wie kann ich den Befehl find in Kombination mit grep verwenden, um Dateien auszuschließen, ist das, was ich wirklich wissen möchte.

pss: Ich bin mir auch nicht sicher, wie man Grep-Unterverzeichnisse in die grep -L *Syntax einbindet , aber ich möchte trotzdem wissen, wie man es mit verwendet find:)

cwd
quelle
1
Der erste Befehl, den Sie geschrieben haben, hat auf meinem Computer einwandfrei funktioniert. Welche Version von find verwenden Sie? Und da wir schon dabei sind, geben Sie vielleicht an, unter welchem ​​Unix Sie arbeiten.
rahmu
@rahmu, dieser Befehl funktioniert fast immer nicht wie erwartet. Sie haben wahrscheinlich einen ganz bestimmten Fall gehabt. Bitte sehen Sie unix.stackexchange.com/questions/339619/…
sgnsajgon

Antworten:

8
find . -type f | xargs grep -H -c 'shared.php' | grep 0$ | cut -d':' -f1    

ODER

find . -type f -exec grep -H -c 'shared.php' {} \; | grep 0$ | cut -d':' -f1

Hier berechnen wir die Anzahl der übereinstimmenden Zeilen (unter Verwendung von -c) in einer Datei, wenn die Anzahl 0 ist, dann ist es die erforderliche Datei, also schneiden wir die erste Spalte, dh den Dateinamen, aus der Ausgabe.

Sachin Divekar
quelle
6
Das ist furchtbar kompliziert. Siehe Kevins Antwort .
Gilles 'SO - hör auf böse zu sein'
@ Gilles ja da stimme ich dir zu. Ich habe +1 auf seine Antwort.
Sachin Divekar
6
Dies ist nicht nur "furchtbar kompliziert", sondern auch falsch, da alle Dateien aufgelistet werden, die ein Vielfaches von 10 Zeilen enthalten, die mit dem Muster übereinstimmen. Selbst wenn grepdies behoben wäre, würde dies immer noch keine Dateinamen :oder Zeilenumbrüche annehmen ...
don_crissti
@don_crissti, danke für die Erwähnung! Wenn Sie nicht viel Code zum Kopieren und Einfügen verwenden, ist die obige Lösung eine nette Spielerei.
Ufos
@Ufos - Ich verstehe deinen Kommentar wirklich nicht ... Das ist falsch . Wie auch immer,
zögern
56

Ihre Suche sollte funktionieren, wenn Sie -v -l(Dateien mit einer nicht übereinstimmenden Zeile) in -L(Dateien ohne übereinstimmende Zeilen) ändern. Sie können jedoch auch die Option greprecursive ( -r) verwenden:

grep -rL shared.php .
Kevin
quelle
welcher find soll funktionieren?
CWD
@ Kevin - sorry, find . -exec grep -v -l shared.php {} \;(und alle anderen Varianten, die ich ausprobiert habe) funktioniert nicht für mich. Ich bin auf OS X, aber ich denke nicht, dass das eine Rolle spielen sollte. Ich habe dir +1 gegeben, weil ich die -rOption vergessen habe .
CWD
@cwd Ich weiß, dass dies alt ist, aber ich möchte dies hier für zukünftige Leser belassen: Die Tatsache, dass Sie unter OS X arbeiten, macht einen Unterschied. Mac OSX verwendet FreeBSD-Befehle. Die meisten Leute hier nehmen Linux-Befehle (GNU) an. Sie haben unterschiedliche Argumente und unterschiedliche Arten, mit Details umzugehen.
Rich Homolka
Ab 2016 scheint OSX zu unterstützen-L
David Moles
@ Kevin Ich sagte, dass es tut, nicht, dass es nicht tut. :) Nicht, dass irgendjemand dies ausdrücklich gesagt hätte, aber die Kommentare waren verwirrend (und ich habe sicherlich andere Probleme mit OS X / BSD gegen GNU).
David Moles
4

Ich weiß, das grep -L *wird dies tun, aber wie kann ich den findBefehl in Kombination mit grepzum Ausschließen von Dateien verwenden, ist das, was ich wirklich wissen möchte

Du könntest folgendes benutzen findund grepmögen:

find . -type f ! -exec grep -q 'PATTERN' {} \; -print

Hier -printwird nur ausgeführt, wenn der vorherige Ausdruck: ! -exec ... {}als ausgewertet wird true.
Also für jede Datei gefunden, grep -q 'PATTERN'wird execausgeschüttete, wenn das Ergebnis falsedann der gesamte Ausdruck ! -exec grep -q 'PATTERN'auswertet , wie trueund der Dateiname printed.

don_crissti
quelle
2
Das hat den Vorteil, dass es Standard und tragbar ist.
Stéphane Chazelas
Es gibt jedoch einen Unterschied zu GNUs grep -L, da auch die nicht lesbaren Dateien in die Liste aufgenommen werden.
Stéphane Chazelas
1

Sie finden kein passendes Ergebnis mit der Option -L

grep -iL shared.php .
Prakash
quelle
-1

Ich denke, Sie suchen nach einem Befehl wie

find . -type f -execdir grep -q -v shared.php {} \; -print

Die Option -qmacht grepverlassen und nach der Verwendung -execdirmüssen Sie -printgefundene Dateien drucken.

Ronin Tom
quelle