Einer meiner Lieblings-BASH-Befehle ist:
find . -name '*.*' -exec grep 'SearchString' {} /dev/null \;
Durchsucht den Inhalt aller Dateien im und unterhalb des aktuellen Verzeichnisses nach dem angegebenen SearchString. Als Entwickler hat sich dies manchmal als nützlich erwiesen.
Aufgrund meines aktuellen Projekts und der Struktur meiner Codebasis möchte ich diesen BASH-Befehl jedoch noch weiter ausbauen, indem ich keine Dateien in oder unter einem Verzeichnis suche, das ".svn" enthält, oder Dateien, die ".svn" enthalten ende mit ".html"
Die MAN-Seite verwirrte mich allerdings. Ich habe versucht, -prune zu verwenden, und es hat mich seltsam verhalten. Bei dem Versuch, nur die HTML-Seiten zu überspringen (um zu beginnen), habe ich Folgendes versucht:
find . -wholename './*.html' -prune -exec grep 'SearchString' {} /dev/null \;
und habe nicht das Verhalten bekommen, auf das ich gehofft hatte. Ich glaube, ich verpasse möglicherweise den Punkt -Prune. Könnt ihr mir helfen?
Vielen Dank
find
ist kein integrierter Bash-Befehl, sondern ein separates Programmgrep -rl 'SearchString'
find
zum Suchen in einer Datei verwendet wird.-name '*.*'
findet nicht alle Dateien: nur die mit einem.
in ihrem Namen (die Verwendung von*.*
ist normalerweise ein DOS-Ismus, während Sie in Unix normalerweise nur*
dafür verwenden). Um wirklich passen sie alle, entfernen Sie einfach das Argument zusammen:find . -exec ...
. Oder wenn Sie grep nur auf Dateien anwenden möchten (und Verzeichnisse überspringen möchten), dann tun Sie diesfind . -type f -exec ...
.Antworten:
Sie können die Negativfunktion (!) Von find verwenden, um Dateien mit bestimmten Namen nicht zuzuordnen:
Wenn der Name also irgendwo im Pfad auf .html endet oder .svn enthält, stimmt er nicht überein, und die Ausführung wird nicht ausgeführt.
quelle
*.*
Übereinstimmung, sicherzustellen, dass nur Dateien mit einem übereinstimmen.
? Suchen stimmt mit allen Dateienname
überein, wenn keine Direktive vorhanden ist. Daher stimmt das oben Gesagte mit allen Dateien außer html und svn überein-wholename '*.svn*'
lieber als-name
..svn
Verzeichnisse aus den Suchergebnissen ausgeschlossen werden.! -name '.'
sollte.
aus den Suchergebnissen ausschließen .Ich habe seit langer Zeit das gleiche Problem und es gibt verschiedene Lösungen, die in verschiedenen Situationen anwendbar sind:
ack-grep
ist eine Art "Entwicklergrep
", der standardmäßig Versionskontrollverzeichnisse und temporäre Dateien überspringt. Auf derman
Seite wird erläutert, wie Sie nur bestimmte Dateitypen durchsuchen und eigene definieren .grep
Die Optionen own--exclude
und--exclude-dir
können sehr einfach verwendet werden, um Datei- Globs und einzelne Verzeichnisse zu überspringen (leider kein Globbing für Verzeichnisse).find . \( -type d -name '.svn' -o -type f -name '*.html' \) -prune -o -print0 | xargs -0 grep ...
sollte funktionieren, aber die oben genannten Optionen sind auf lange Sicht wahrscheinlich weniger problematisch.quelle
Der folgende
find
Befehl löscht Verzeichnisse, deren Namen enthalten.svn
. Obwohl er nicht in das Verzeichnis abfällt, wird der Name des gelöschten Pfads gedruckt ... (-name '*.svn'
ist die Ursache!).Sie können die Verzeichnisnamen herausfiltern über
grep -d skip
:, wodurch solche eingegebenen "Verzeichnisnamen" unbemerkt übersprungen werden.Mit GNU grep können Sie
-H
anstelle von verwenden/dev/null
. Als kleines Nebenthema:\+
Kann viel schneller sein als\;
z. Für 1 Million einzeilige Dateien\;
dauerte die Verwendung 4 Minuten und 20 Sekunden . Die Verwendung\+
dauerte nur 1,2 Sekunden .Die folgende Methode verwendet
xargs
statt-exec
und nimmt es keine Zeilenumbrüche sind\n
in Ihren Dateinamen . Wie hier verwendet,xargs
ist so ziemlich dasselbe wie bei find's\+
.xargs
Sie können Dateinamen, die aufeinanderfolgende Leerzeichen enthalten, übergeben, indem Sie das Eingabetrennzeichen'\n'
mit der-d
Option auf ändern .Dies schließt Verzeichnisse , deren Namen enthalten
.svn
und greps nur Dateien , die mit nicht enden.html
.quelle
\+
Variante der Aktion -exec. Hurra für leichte Nebenprobleme!+
es sich bei der Shell nicht um ein Sonderzeichen handelt, müssen Sie natürlich nicht\
vorher tippen .