find

aus Wikipedia, der freien Enzyklopädie
Wechseln zu: Navigation, Suche

find (/usr/bin/find) ist ein Programm für das Filemanagement und ein grundlegender Bestandteil der Softwareausstattung von Unix und Unix-ähnlichen Betriebssystemen. Es ist Teil des POSIX-Standards (IEEE Std 1003.1)[1] und der Single UNIX Specification.

Unter Microsoft Windows gibt es ebenfalls den Befehl find, dieser durchsucht jedoch den Inhalt von Dateien und hat eher (entfernte) Ähnlichkeit mit dem Unix-Kommando grep.

Geschichte[Bearbeiten | Quelltext bearbeiten]

Das erste find erschien in Version 5 Unix (ca. Juni 1974) als Teil des Programmer's Workbench-Projekts. Es wurde von Richard C. (Dick) Haight geschrieben, ebenso wie cpio und expr.[2] find und cpio wurden für den gemeinsamen Einsatz entworfen.

Arbeitsweise[Bearbeiten | Quelltext bearbeiten]

Ausgehend von einem anzugebenden Basisverzeichnis durchschreitet find die Filesystemstruktur rekursiv und erzeugt eine Liste von Filesystem-Inhalten (Files, Directories, etc..), die (wenigstens in den meisten Fällen) auf <stdout> ausgegeben wird. Diese Liste kann durch ein oder mehrere Operanden nach verschiedenen Gesichtspunkten fortschreitend eingeschränkt werden:

find /some/dir -print                     # jeden Eintrag in /some/dir anzeigen
find /some/dir -type f -print             # angezeigte Einträge auf (reguläre) Dateien beschränken
find /some/dir -type f -name 'x*' -print  # angezeigte Einträge auf Dateien deren Namen mit "x" beginnt, einschränken

Es ist möglich, mehrere solche Operanden durch logische Operationen (UND, ODER, NICHT) zu verknüpfen wie auch durch Klammern die Präzendenz der Operanden zu beeinflussen. So können auch komplexe Filtertypen realisiert werden.

Allen Operanden ist gemeinsam, dass sie als Ergebnis ein logisches TRUE oder FALSE zurückgeben, aufgrund dessen die gerade untersuchte Entität an der weiteren Verarbeitung teilnimmt (bis sie - üblicherweise - am Schluß ausgegeben wird) oder von derselben ausgeschlossen wird.

Es ist möglich, das Ausgabeformat auf den reinen Dateinamen zu beschränken (-print) oder auch eine Liste von Attributen in Tabellenform (-ls, was eine Ausgabe ähnlich der des Kommandos ls -ails bewirkt) auszugeben.

-exec[Bearbeiten | Quelltext bearbeiten]

Eine besondere Stellung unter den Operanden nimmt -exec ein. Es erwartet als Argument ein (einfaches oder auch zusammengesetztes) Kommando, in welchem der Name der gerade untersuchten Entität durch das Symbol {} vertreten wird. Damit ist es möglich, für eine eben erzeugte Liste von Filesystem-Einträgen eine durch ein Kommando repräsentierte Aktion durchzuführen. Das Beispiel sucht in allen Dateien *.c in dem Directory /some/dir nach Aufrufen oder dem Code der Funktion myfunc() (die Datei /dev/null wird angegeben, damit grep die Dateinamen der Fundstellen mit anzeigt):

find /some/dir -type f -name '*\.c' -exec grep 'myfunc(' /dev/null {} \;

Darüber hinaus gibt -exec als Rückgabewert den Return Code des aufgerufenen Kommandos zurück, sodass es ebenfalls für Filterungszwecke genutzt werden kann. Falls im obigen Beispiel nur die Dateinamen der Dateien, in denen die Funktion verwendet wird, gesucht werden, so kann dies durch:

find /some/dir -type f -name '*\.c' -exec grep -q 'myfunc(' {} \; -print

geschehen.

Hinweise und Einschränkungen[Bearbeiten | Quelltext bearbeiten]

Numerische Argumente[Bearbeiten | Quelltext bearbeiten]

Verschiedene Operanden (zum Beispiel -size oder -atime) erwarten numerische Argumente. Bei solchen gilt, dass die Angabe n (für numerische Werte n) immer genau n bedeutet, -n hingegen kleiner als n und +nbedeutet größer als n.

Vorsicht bei -exec[Bearbeiten | Quelltext bearbeiten]

Da oftmals beim Aufruf von find nicht feststeht, wieviele Treffer schließlich im Ergebnis-Set vorliegen, kann die Verwendung von -exec zu einer unverhältnismäßigen Belastung des Systems führen, da ja für jeden Treffer ein (durch vergleichsweise hohen Ressourcenverbrauch gekennzeichneter) fork()-Systemcall durchzuführen ist.

Einige (nicht dem POSIX-Standard entsprechende) Implementationen kennen deshalb das den externen Aufruf abschließende Plus (\+) oder auch den alternativen Operanden -execplus. Beide rufen das externe Kommando mit einer Liste von Treffern gleichzeitig auf, sodass die erwähnte Belastung des Systems durch viele fork()-s verringert wird. Gleichzeitig aber wird der Rückgabewert des Kommandos für eine einzelne Datei unbestimmt, sodass -exec nicht mehr weiter als filternder Operand wirken kann.

Weitere Probleme bei der Verwendung von -exec können sich bei komplexen Kommandos ergeben: es ist zwar grundsätzlich möglich, verschachtelte Kommandos zu verwenden, aber letztlich ist find keine Shell und deshalb in der Interpretation solcher Schachtelungen beschränkt. Insbesondere Shell-übliche Konstruktionen wie etwa die logische Verknüpfung cmd1 && cmd2 schlagen innerhalb von Kommandos in -exec fehl.

{} und -exec[Bearbeiten | Quelltext bearbeiten]

Das Argument {} kann lediglich ein einziges Mal in einem -exec-Operanden verwendet werden, nicht öfter. Darüber hinaus muss es als einzelnes (das heißt alleinstehendes) Argument verwendet werden. Die folgenden Konstruktionen sind deshalb alle ungültig:

find /some/where type f -exec mv {} {}.old \;
find /some/where type f -exec gzip {} >/packed/files/{} \;

Für solche Zwecke sollte ein Script geschrieben werden, dem als Parameter der Dateiname übergeben wird und das als Argument in -exec eingesetzt wird. Etwa für das erste Beispiel:

$ cat > /tmp/mymove.sh
mv $1 ${1}.old
^D

$ find /some/where type f -exec /tmp/mymove.sh {} \;

Weblinks[Bearbeiten | Quelltext bearbeiten]

Einzelnachweise[Bearbeiten | Quelltext bearbeiten]

  1. find (Opengroup Base Specifications Issue 6). Abgerufen am 8. März 2018 (englisch).
  2. M. Douglas McIlroy: A Research Unix reader: annotated excerpts from the Programmer's Manual, 1971–1986. Abgerufen am 8. März 2018 (pdf, englisch).