Table of Contents

find

find ist ein umfangreiches Kommandozeilenprogramm für die Dateisuche. Die Suche selbst lässt sich sehr genau mit diversen Filtern für Dateinamen,- typen, -größen und mehr erweitern und kann mit diversen Aktionen kombiniert werden. Eine simplere Suche, bei der nur nach Dateinamen gesucht wird und Treffer im Dateisystem ausgegeben werden, lässt sich mit 'locate' durchführen.

find läuft rekursiv durch die Verzeichnishierarchie, ausgehend von einem Startverzeichnis, versucht Treffer zu den angegebenen Kriterien zu finden und kann anschließend noch Aktionen damit ausführen. Wird nur find aufgerufen, wird als Standardverzeichnis . angenommen und es werden alle Dateien gefunden, inklusive Ordner, symbolische Links, Geräte etc., frei nach dem Leitsatz "Everything is a file". Wird keine Aktion angegeben, wird in der Regel von -print ausgegangen, also die Ergebnisse werden auf der Konsole ausgegeben. Sollen beispielsweise alle mp3-Dateien ausgehend vom aktuellen Verzeichnis ausgegeben werden, lautet der Befehl

find . -name '*.mp3' -print

Oder kurz nur find -name '*.mp3'.

Logische Operationen

Logische Operationen sind auch möglich, so lässt sich beispielsweise nach allen mp3- und ogg-Dateien suchen:

find . \( -name '*.mp3' -o -name '*.jpg' \) -print

Dabei steht -o für or. Ein and lässt sich implizit durch die Eingabe mehrerer flags erreichen:

find . -name '*.mp3' -name '*.jpg' -print

Kombinationen sind ebenfalls möglich:

find . \( -name '*.mp3' -o -name '*.jpg' \) -name 'foo*' -print

Statt nur -name, was je nach Muster nur Dateinamen oder auch Pfade findet, kann mit -path speziell nach Verzeichnisnamen gesucht werden. Dabei ist jedoch zu beachten, dass ein find -path 'bar*' beispielsweise das Verzeichnis ./bar nicht findet, da es mit dem aktuellen Verzeichnis, also ., beginnt. Die Suche find -path './bar*' hingegen findet das Verzeichnis und listet dessen Inhalt.

Eine Negation mittels ! oder -not ist auch möglich, um Begriffe oder Pfade auszuschließen:

find . -name '*.mp3' ! -path '*bar*' -print

So werden alle mp3-Dateien gesucht, wobei Pfade, die “bar” enthalten, ausgeschlossen werden.

Suchkriterien

Es gibt eine Vielzahl an nutzbaren Suchkriterien wie bereits eingangs erwähnt. Die folgende grobe und nicht vollständige Übersicht soll lediglich eine Idee für die Möglichkeiten geben. Eine vollständige Übersicht liefert die Manpage (man find).

Startverzeichnis

Dateityp

Name

Größe

Alter

Wie bei der Größe gibt es auch hier + für ein Mindestalter, - für ein Höchstalter und ohne Angabe ein exaktes Alter.

Sonstiges

Kombinationsbeispiele

Finde Dateien ab dem zweiten bis zum maximal vierten Unterverzeichnis, die größer als 25 MB sind und weder .avi, noch .mpg oder .mpeg-Dateien sind:

find -mindepth 2 -maxdepth 4 ! -name "*.avi" -not -name "*.mp*g" -size +25M

Wie bei den logischen Operationen bereits gezeigt, kann eine Klammerung nötig sein, um das gewünschte Resultat zu erzielen. Dabei ist zu beachten, dass eine Klammerung die Reihenfolge der Kombination ändert.

find -name "foo.*" -or -name "bar.*" -name "*.txt"

Ohne Klammern wird zuerst die and-Kombination gebildet, also “bar.*” und “*.txt”, danach erst das or “foo.*”. So würde also ein “foo.jpg” gefunden.

find \( -name "foo.*" -or -name "bar.*" \) -name "*.txt"

Die Klammern müssen maskiert werden! In diesem Fall wird nach “foo.*” oder “bar.*” gesucht, allerdings wird erfordert, dass alle Ergebnisse auf “*.txt” enden müssen.

Aktionen

Anstelle der Ausgabe mittels -print können die gefunden Dateien auch gelöscht werden:

  1. exec rm -f {} \;

Dabei gibt -exec an, wir wollen jetzt ein Kommando ausführen, in diesem Fall rm -f, welches mit ; terminiert wird. Da ein Semikolon allerdings ein spezielles Zeichen in der Shell ist, muss es mit \ maskiert werden. Die geschweiften Klammern sind ein spezielles Argument für find. Jedes Mal, wenn eine Datei gefunden wurde und -exec ausgeführt wird, werden die geschweiften Klammern {} durch den jeweiligen Dateinamen ersetzt.

Ein Beispiel ist es, alle temporären Dateien zu löschen, die länger als 30 Stunden nicht mehr geändert wurden:

find /tmp -type f -mtime +30 -exec rm -f {} \;

Neben -exec gibt es auch -delete, welches die gefundenen Dateien und leeren Verzeichnisse löscht. So kann der zu Beginn dieses Abschnitts angegebene Befehlsteil durch ein delete ersetzt werden.

Weitere Aktionen sind:

Anwendungsbeispiele

Einige konkretere Anwendungsbeispiele für find. Erklärungen zu komplexeren Beispielen mit xargs und mehr können hier gefunden werden.

Prüfsumme mit ''execdir +''

Erstelle für alle komprimierten tar-Archive eine MD5-Prüfsumme:

find <directory> -type f -name '*.tar.*' -execdir md5sum {} +

In diesem Fall kommt md5sum auch mit einer Liste von Dateien klar, also statt

md5sum a
md5sum b
md5sum c

zu verwenden, was bei dem Aufruf mit -execdir md5sum {} \; passieren würde, kann auch eine Liste von Dateien übergeben werden, wenn die Suche abgeschlossen ist (+):

md5sum a b c

Größte Dateien finden

Finde die größten Dateien in einem Verzeichnis, beginnend bei 20 MB, und sortiere sie nach der Größe:

find <Verzeichnis> -type f -size +20M -exec ls -sh {} \; 2> /dev/null | sort -rh

Zuletzt erstellte Dateien finden

Manchmal kommt es vor, dass plötzlich eine Aktion Speicherplatz benötigt und / oder man herausfinden will, was zuletzt auf der Festplatte erstellt wurde. Dazu kann man mit

find / -ctime -2

herausfinden, welche Daten innerhalb der letzter 2 Stunden erstellt wurden (Änderung ihres Status). Oder innerhalb der letzten 15 Minuten:

find / -cmin -15

Das ganze habe ich mir, da es ab und an mal vorkommt, dass z. B. ein Core dump oder etwas anderes mein root-Verzeichnis zumüllt, als Funktion in meiner .bashrc angelegt. Wird keine Option verwendet, wird ausgehend von / nach Daten gesucht, die innerhalb der letzten 15 Minuten erstellt wurden (s. Kommando oben).

function last_files(){
    local d=$1
    local t=$2
    [ "$d" == "" ] && d='/'
    [ "$t" == "" ] && t=15
    echo -e "--> Find files created less than $t minutes ago,\n    starting from directory '$d':\n"
    find "$d" -cmin -$t
}