Wie finde ich die Dateien im aktuellen Verzeichnis heraus, die das Wort nicht enthalten foo
(using grep
)?
Wie finde ich die Dateien im aktuellen Verzeichnis heraus, die das Wort nicht enthalten foo
(using grep
)?
Antworten:
Wenn Ihr grep die Option -L
(oder --files-without-match
) hat:
$ grep -L "foo" *
GREP_OPTIONS='--exclude-dir=.svn --exclude-dir=.git'
: ^)
-rL
anstelle von -L
, um Unterverzeichnisse
grep -L 'foo' -- *
Standardmäßig werden Befehle mit langen Optionen verwendet, --
um anzuzeigen, dass nach diesem Punkt keine Optionen mehr vorhanden sind.
Schau es dir an ack
. Es schließt den .svn
Ausschluss automatisch für Sie aus, gibt Ihnen reguläre Perl-Ausdrücke und ist ein einfacher Download eines einzelnen Perl-Programms.
Das Äquivalent zu dem, was Sie suchen, sollte sein in ack
:
ack -L foo
Sie können es mit grep alleine machen (ohne zu finden).
grep -riL "foo" .
Dies ist die Erklärung der verwendeten Parameter grep
-L, --files-without-match
each file processed.
-R, -r, --recursive
Recursively search subdirectories listed.
-i, --ignore-case
Perform case insensitive matching.
Wenn Sie l
(Kleinbuchstaben) verwenden, erhalten Sie das Gegenteil (Dateien mit Übereinstimmungen)
-l, --files-with-matches
Only the names of files containing selected lines are written
Der folgende Befehl gibt mir alle Dateien, die das Muster nicht enthalten foo
:
find . -not -ipath '.*svn*' -exec grep -H -E -o -c "foo" {} \; | grep 0
grep '0$'
Würde aber auch Dateien mit Vielfachen von 10 Zeilen abgleichen ! Sie müssen grep ':0$'
am Ende nach einem expliziten ': 0' am Ende der Zeile suchen. Dann erhalten Sie nur Dateien mit übereinstimmenden Nullzeilen.
Der folgende Befehl schließt die Notwendigkeit aus, dass die Suche die svn
Ordner mithilfe einer Sekunde herausfiltert grep
.
grep -rL "foo" ./* | grep -v "\.svn"
Sie benötigen tatsächlich:
find . -not -ipath '.*svn*' -exec grep -H -E -o -c "foo" {} \; | grep :0\$
Problem
Ich muss ein großes Projekt umgestalten, das .phtml
Dateien verwendet, um HTML mit Inline-PHP-Code zu schreiben. Ich möchte stattdessen Moustache- Vorlagen verwenden. Ich möchte alle .phtml
Giles finden, die die Zeichenfolge nicht enthalten, new Mustache
da diese noch neu geschrieben werden müssen.
Lösung
find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'
Erläuterung
Vor den Rohren:
Finden
find .
Suchen Sie rekursiv nach Dateien, beginnend in diesem Verzeichnis
-iname '*.phtml'
Der Dateiname muss enthalten .phtml
(das i
macht es unabhängig von Groß- und Kleinschreibung)
-exec 'grep -H -E -o -c 'new Mustache' {}'
Führen Sie den grep
Befehl auf jedem der übereinstimmenden Pfade aus
Grep
-H
Drucken Sie Dateinamen-Header immer mit Ausgabezeilen.
-E
Interpretieren Sie das Muster als erweiterten regulären Ausdruck (dh zwingen Sie grep, sich als egrep zu verhalten).
-o
Druckt nur den passenden Teil der Zeilen.
-c
Es wird nur eine Anzahl ausgewählter Zeilen in die Standardausgabe geschrieben.
Dies gibt mir eine Liste aller Dateipfade .phtml
, die mit enden , mit einer Zählung, wie oft die Zeichenfolge new Mustache
in jedem von ihnen vorkommt.
$> find . -iname '*.phtml$' -exec 'grep -H -E -o -c 'new Mustache' {}'\;
./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/orders.phtml:1
./app/MyApp/Customer/View/Account/banking.phtml:1
./app/MyApp/Customer/View/Account/applycomplete.phtml:1
./app/MyApp/Customer/View/Account/catalogue.phtml:1
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0
Die erste Pipe grep :0$
filtert diese Liste so, dass sie nur Zeilen enthält, die auf Folgendes enden :0
:
$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$
./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0
Die zweite Pipe sed 's/..$//'
entfernt die letzten beiden Zeichen jeder Zeile und lässt nur die Dateipfade übrig.
$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'
./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml
./app/MyApp/Customer/View/Account/studio.phtml
./app/MyApp/Customer/View/Account/classadd.phtml
./app/MyApp/Customer/View/Account/orders-trade.phtml
Wenn Sie git verwenden, werden alle nachverfolgten Dateien durchsucht:
git grep -L "foo"
und Sie können in einer Teilmenge der verfolgten Dateien suchen, wenn Sie das shopt -s globstar
Globbing des Unterverzeichnisses ** aktiviert haben ( in .bashrc, siehe dies ):
git grep -L "foo" -- **/*.cpp
Mein grep hat keine -L Option. Ich finde eine Problemumgehung, um dies zu erreichen.
Die Ideen sind:
Machen Sie den Unterschied zwischen der 2-Dump-Datei mit dem Befehl diff.
grep 'foo' *.log | cut -c1-14 | uniq > txt1.txt
grep * *.log | cut -c1-14 | uniq > txt2.txt
diff txt1.txt txt2.txt | grep ">"
diff
auszugeben , können Sie tatsächlich einen zwischen zwei Ausgabestreams ausführen (ich denke, Sie umgeben die Befehle mit Klammern, und irgendwo gibt es auch eine spitze Klammer), wenn Ihr System dies unterstützt, was ich denke ist die Frage, da es nicht unterstütztgrep -L
find *20161109* -mtime -2|grep -vwE "(TRIGGER)"
Sie können den Filter unter "find" und die Ausschlusszeichenfolge unter "grep -vwE" angeben. Verwenden Sie mtime unter find, wenn Sie auch nach geänderter Zeit filtern müssen.
Wie von @tukan kommentiert, gibt es für Ag einen offenen Fehlerbericht bezüglich der -L
/ --files-without-matches
flag:
Da der Fehlerbericht kaum Fortschritte macht, sollte auf die -L
unten genannte Option nicht vertraut werden , solange der Fehler nicht behoben wurde. Verwenden Sie stattdessen verschiedene in diesem Thread vorgestellte Ansätze. Zitieren eines Kommentars für den Fehlerbericht [Hervorhebung von mir]:
Irgendwelche Updates dazu?
-L
Ignoriert Übereinstimmungen in der ersten Zeile der Datei vollständig. Wenn dies nicht bald behoben wird, sollte das Flag vollständig entfernt werden, da es effektiv überhaupt nicht wie angekündigt funktioniert .
Als leistungsstarke Alternative zu grep
können Sie The Silver Searcher - Ag verwenden :
Ein Code-Suchwerkzeug ähnlich wie ack mit Schwerpunkt auf Geschwindigkeit.
Beim Betrachten man ag
finden wir die Option -L
oder --files-without-matches
:
... OPTIONS ... -L --files-without-matches Only print the names of files that don´t contain matches.
Dh, um rekursiv nach Dateien zu suchen, die nicht übereinstimmen foo
, aus dem aktuellen Verzeichnis:
ag -L foo
Um nur das aktuelle Verzeichnis nach Dateien zu durchsuchen , die nicht übereinstimmen foo
, geben Sie einfach --depth=0
für die Rekursion Folgendes an:
ag -L foo --depth 0
-L
Fehlers fehl - github.com/ggreer/the_silver_searcher/issues/238
grep -irnw "filepath" -ve "pattern"
oder
grep -ve "pattern" < file
Der obige Befehl gibt uns das Ergebnis, wenn -v die Umkehrung des gesuchten Musters findet
-l
Option hinzufügen , nur den Dateinamen zu drucken. aber das druckt immer noch die Namen der Datei , die enthält jede Zeile , die das Muster nicht enthalten. Ich glaube, das OP möchte die Dateien finden, die keine Zeile enthalten, die das Muster enthält.
Der folgende Befehl kann Ihnen helfen, die Zeilen zu filtern, die den Teilstring "foo" enthalten.
cat file | grep -v "foo"
cat
.