it-swarm.com.de

Wie ignoriere ich bestimmte Dateinamen mit "find"?

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 weiterentwickeln, 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 für den Fund hat mich allerdings etwas verwirrt. 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 bekam nicht das Verhalten, auf das ich gehofft hatte. Ich denke, ich könnte den Punkt -Prune verpassen. Könnt ihr mir helfen?

Vielen Dank

128
Cody S

Sie können die Negativfunktion (!) Von find verwenden, um Dateien mit bestimmten Namen nicht zuzuordnen:

find . ! -name '*.html' ! -path '*.svn*' -exec grep 'SearchString' {} /dev/null \;

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.

179
Paul

Ich habe seit langer Zeit das gleiche Problem und es gibt verschiedene Lösungen, die in verschiedenen Situationen anwendbar sind:

  • ack-grepist eine Art "Entwickler grep", die standardmäßig Versionskontrollverzeichnisse und temporäre Dateien überspringt. Auf der Seite man erfahren Sie, wie Sie nur nach bestimmten Dateitypen suchen und Ihre eigenen definieren .
  • Die grep -Optionen --exclude und --exclude-dir können sehr einfach zum Überspringen der Verzeichnisse Globs und Single verwendet werden.
  • 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.
10
l0b0

Der folgende Befehl find entfernt Verzeichnisse, deren Namen enthalten .svn sind. Obwohl er nicht in das Verzeichnis abfällt, wird der beschnittene Pfadname gedruckt ... (-name '*.svn' ist die Ursache!).

Sie können die Verzeichnisnamen über Folgendes herausfiltern: grep -d skip, wodurch solche eingegebenen "Verzeichnisnamen" unbemerkt übersprungen werden.

Mit GNU grep können Sie -H anstelle von /dev/null verwenden. Als geringfügiges Nebenproblem: \+ kann viel schneller sein als \;, z. Für 1 Million einzeilige Dateien wurden mit \; 4m20s , mit \+ nur 1,2s benötigt.

Die folgende Methode verwendet xargs anstelle von -exec und setzt voraus, dass in keiner Ihrer Dateien names Zeilenumbrüche \n enthalten sind. Wie hier verwendet, ist xargs dem \+ von find sehr ähnlich.

xargs kann Dateinamen übergeben, die aufeinanderfolgende Leerzeichen enthalten, indem das Eingabetrennzeichen mit der Option '\n' in -d geändert wird.

Dies schließt Verzeichnisse aus, deren Namen.svn enthalten, und greift nur auf Dateien zu, die nicht mit .html enden.

find . \( -name '*.svn*' -Prune  -o ! -name '*.html' \) |
   xargs -d '\n' grep -Hd skip 'SearchString'
7
Peter.O