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 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.
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).
find oder find .find foo find /foo /tmp /varfind -type ffind -type dfind -name foo.barfind -iname '*.jpg'find -name cat.??g' findet unter anderem cat.jpg und cat.png.find -name '*foo*.*x'find -size -100c -ls sucht Dateien, die bis zu 100 Bytes groß sind. Für das “bis zu” steht das -, c steht für “character”, die früher 1 Byte belegten (b ist bereits für “block” vergeben), und -ls liefert eine Auflistung, bei der auch die Größe angezeigt wird.find -size 100c -lsfind -size +10M sucht Dateien, die größer als 10 MB sind. Für “größer” steht das +, statt M kann auch k oder G für kB oder GB verwendet werden.find -type f -size +64c -size -256c sucht nur nach Dateien, die zwischen 64 und 256 Bytes groß sind.
Wie bei der Größe gibt es auch hier + für ein Mindestalter, - für ein Höchstalter und ohne Angabe ein exaktes Alter.
find -mtime -365 findet Dateien, die innerhalb der letzter 365 Tage geändert wurden (modification time).ctime: change time, Zeitpunkt der Änderung des Status einer Datei (Name, Rechte), womit sich beispielsweise auch erstellte Dateien finden lassen.atime: access time, Zeitpunkt des Zugriffs auf eine Datei. Bei Bilddateien zählt auch schon die Vorschaufunktion eines grafischen Dateibrowsers. Die Zugriffszeit wird allerdings nicht bei jedem Lesen aktualisiert, erst ab 24h Abweichung.find -cmin -5find -cnewer /path/rerefence.filefind -emptyfind -maxdepth 3 sucht bis zum maximal dritten Unterverzeichnisfind -mindepth 2 sucht ab dem zweiten Unterverzeichnisfind / -user <username>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.
Anstelle der Ausgabe mittels -print können die gefunden Dateien auch gelöscht werden:
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:
-ls: Wie weiter oben bereits erwähnt, wird so eine ausführlichere Ausgabe erzeugt.-fprint <filename>: Statt der Ausgabe in der Konsole werden die gefundenen Dateinamen in die Datei <filename> geschrieben.-execdir <command> {} +: Analog zu -exec, allerdings wird das Kommando im Gegensazu zu -exec im Verzeichnis ausgeführt, in dem die jeweilige Datei gefunden wurde. Das + kann (wie auch bei -exec) statt des Semikolons verwendet werden, wenn {} der letzte Parameter ist; so werden alle Funde auf einmal an das Kommando übergeben (s. Beispiel ''md5sum'' weiter unten).-ok <command> {} \;: Wie -exec, jedoch wird vor jeder Aktion um eine Bestätigung gefragt.-okdir: Wie eine Kombination aus -ok und -execdir.
Einige konkretere Anwendungsbeispiele für find. Erklärungen zu komplexeren Beispielen mit xargs und mehr können hier gefunden werden.
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
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
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 }