HOWTO · Bash
find -exec-Befehl in der Bash ausführen
Dieser Artikel zeigt, wie Sie mit dem Parameter -exec des Befehls find Dateipfade auswählen und mit grep den Inhalt dieser Dateien durchsuchen.
Auf dieser Seite
find wählt Dateisystempfade aus; grep durchsucht Dateiinhalte. Die Aktion -exec verbindet beides, indem sie jeden ausgewählten Pfad als Argument an einen anderen Befehl übergibt. Dieser Leitfaden zeigt eine wiederverwendbare Syntax, die Suche in Dateiinhalten, den Unterschied zwischen einem Aufruf pro Treffer und gebündelten Pfaden sowie vorsichtige Dateioperationen.
So funktioniert find -exec
find beginnt in einem angegebenen Verzeichnis, prüft Bedingungen wie Dateityp, Name, Alter oder Größe und durchläuft passende Pfade. Mit -exec ruft es den angegebenen Befehl auf und setzt für {} jeweils den gefundenen Pfad ein. Der Pfad wird als Argument übergeben. Deshalb werden Leerzeichen, Tabulatoren, Anführungszeichen und Platzhalterzeichen in einem Dateinamen nicht erneut von einer Shell ausgewertet. Das ist sicherer, als eine Befehlszeichenfolge zusammenzusetzen oder durch Zeilenumbrüche getrennte Dateinamen an einen anderen Befehl weiterzureichen.
Suche und Aktion sind getrennte Aufgaben: Eine Bedingung wie -name '*.txt' wählt Dateien aus, während ein Befehl wie grep deren Inhalt liest. Fügen Sie -type f hinzu, wenn die Aktion nur reguläre Dateien betreffen soll. Standardmäßig berücksichtigt find auch Verzeichnisse. Wählen Sie daher Bedingungen, die zur Eingabe passen, die der Befehl erwartet.
Grundlegende Syntax von find -exec
Die wiederverwendbare Form lautet find STARTING_PATH TESTS -exec COMMAND {} \\;. STARTING_PATH legt den zu durchsuchenden Verzeichnisbaum fest; die Bedingungen beschränken, welche Pfade an die Aktion übergeben werden; COMMAND und seine Optionen bestimmen die auszuführende Arbeit; und {} markiert die Stelle, an der find einen Pfad einsetzt. Geben Sie in einer interaktiven Shell den Abschluss als \\; an, damit die Shell ein wörtliches Semikolon an find weitergibt. Ohne diese Maskierung oder Anführungszeichen behandelt die Shell das Semikolon als Befehlsseparator.
Setzen Sie Dateinamensmuster wie '*.txt' in Anführungszeichen. So übergibt die Shell das Muster unverändert, damit find die Namen an jedem durchsuchten Pfad prüft, statt das Muster auf Dateien im aktuellen Verzeichnis anzuwenden. Pfade, die mit einem Bindestrich beginnen, sollten Sie mit einem expliziten Startverzeichnis wie ./-archive angeben, damit sie nicht als Befehlsoptionen missverstanden werden.
Führen Sie dieses Beispiel aus:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
set -eu
root=$(mktemp -d)
trap 'rm -rf "$root"' EXIT
mkdir -p "$root/notes"
printf 'report: first\nkeep this line\n' > "$root/notes/weekly report.txt"
printf 'draft only\n' > "$root/notes/draft.txt"
find "$root" -type f -name '*.txt' -exec grep -nH 'report' {} +
Das Beispiel legt ein eigenes kleines Verzeichnis an, durchsucht nur Textdateien und lässt grep passende Zeilennummern und Dateinamen ausgeben. -H sorgt dafür, dass der Dateiname auch dann angezeigt wird, wenn ein einzelner Aufruf nur einen Pfad erhält. Beim Beenden der Shell wird das temporäre Verzeichnis entfernt. Das Beispiel lässt sich ausführen; eine konkrete Ausgabe wird hier nicht behauptet.
Dateiinhalte mit find und grep durchsuchen
Um Text unter /documents zu durchsuchen, verwenden Sie find /documents -type f -name '*.txt' -exec grep -nH 'report' {} +. find wählt die infrage kommenden Textdateien aus, und grep gibt jede passende Zeile mit Pfad und Zeilennummer aus. Verwenden Sie grep -l statt -nH, wenn Sie nur die Namen der Dateien benötigen, die einen Treffer enthalten. Eine Datei kann mehrere passende Zeilen enthalten; bei der zeilenweisen Ausgabe kann derselbe Pfad daher mehrfach erscheinen.
Da die Suchzeichenfolge in Anführungszeichen steht, wird sie wörtlich als einzelnes Argument übergeben. Legen Sie bei regulären Ausdrücken den gewünschten Ausdruck bewusst fest. Bei einer festen Zeichenfolge verhindert grep -F, dass Zeichen mit besonderer Bedeutung in regulären Ausdrücken interpretiert werden. Eine Textsuche kann eine Datei wegen fehlender Leseberechtigung oder ihrer Kodierung nicht lesen. Berücksichtigen Sie beim Skripten deshalb auch Diagnosemeldungen und den Exit-Status des Befehls. Beispielpfade sind hier nicht aufgeführt, da Treffer von den Dateien im jeweiligen Verzeichnis abhängen.
Zwischen ; und + wählen
Mit -exec COMMAND {} \\; führt find den Befehl für jeden passenden Pfad einzeln aus. Diese Form ist leicht verständlich und eignet sich für Befehle, die jeweils einen Pfad verarbeiten sollen. Das für die Shell maskierte Semikolon beendet die Aktionsdefinition; es gehört nicht zum ausgeführten Befehl.
Mit -exec COMMAND {} + übergibt find jedem Befehlsaufruf mehrere passende Pfade und teilt sie in Gruppen auf, die innerhalb der Argumentgrößenbeschränkung des Systems liegen. Setzen Sie {} genau einmal als letztes Befehlsargument unmittelbar vor +. Die Bündelung verringert oft den Aufwand für Prozessstarts, etwa bei Werkzeugen wie grep. Sie ändert jedoch nicht, was diese Werkzeuge mit den einzelnen Dateien tun, und eignet sich nicht für Befehle, deren Bedeutung davon abhängt, genau einen Pfad zu erhalten. Das Pluszeichen wird direkt an find übergeben und muss nicht für die Shell maskiert werden.
Weitere Befehle sicher auf passenden Dateien ausführen
Prüfen Sie vor dem Entfernen alter Protokolldateien zunächst die ausgewählten Pfade, indem Sie die Aktion durch -print ersetzen: find /var/log -type f -name '*.log' -mtime +30 -print. Die Bedingung -mtime +30 wählt Dateien aus, deren Änderungszeit mehr als 30 volle Zeiträume von jeweils 24 Stunden zurückliegt. Sie bedeutet nicht „älter als der dreißigste Kalendertag“. Nachdem Sie die Auswahl geprüft haben und über die nötigen Berechtigungen verfügen, unterstützen GNU und viele andere Implementierungen von find die Option -delete, zum Beispiel: find /var/log -type f -name '*.log' -mtime +30 -delete. Mit diesem Befehl gelöschte Dateien lassen sich nicht wiederherstellen. Prüfen Sie daher vor der Ausführung das Startverzeichnis und die Bedingungen.
Um reguläre Dateien mit mehr als 100 Mebibyte aus einem Download-Verzeichnis zu verschieben, prüfen Sie zunächst die Auswahl mit find /downloads -type f -size +100M -print. Wenn die Liste stimmt, /archive/ auf demselben System vorhanden ist und die nötigen Berechtigungen vorliegen, können Sie die Dateien einzeln verschieben: find /downloads -type f -size +100M -exec mv -- {} /archive/ \\;. Die Größenbedingung +100M verwendet die Größeneinheiten von find und rundet auf die nächste Einheit auf. Wenn es auf einen exakten Grenzwert in Byte ankommt, prüfen Sie die Einheitendefinition der jeweiligen Implementierung. Beim Verschieben können Dateien am Ziel überschrieben werden oder mit dort bereits vorhandenen Namen kollidieren. Prüfen Sie deshalb vorher, ob Dateinamen doppelt vorkommen. Halten Sie bei beiden Aufgaben die Auswahlbedingungen eng und kontrollieren Sie die Vorschau, bevor Sie Dateien ändern.