====== 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 [[https://de.wikipedia.org/wiki/Everything_is_a_file|"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 [[http://linux.die.net/man/1/find|Manpage]] (''man find''). ==== Startverzeichnis ==== * Suche im aktuellen Verzeichnis: ''find'' oder ''find .'' * Suche im Unterverzeichnis "foo" des aktuellen Verzeichnisses: ''find foo'' * Suche beginnend im Wurzelverzeichnis, also überall: '' find /'' * Suche in zwei Verzeichnissen: ''foo /tmp /var'' ==== Dateityp ==== * Suche nur nach Dateien: ''find -type f'' * Suche nur nach Verzeichnissen: ''find -type d'' ==== Name ==== * Suche nach vollständigem Namen: ''find -name foo.bar'' * Suche nach **.jpg** und **.JPG**: ''%%find -iname '*.jpg'%%'' * Suche mit Wildcards für einzelne Zeichen: ''%%find -name cat.??g'%%'' findet unter anderem cat.jpg und cat.png. * Suche mit Kombinationen von Wildcards: ''%%find -name '*foo*.*x'%%'' ==== Größe ==== * Maximale Größe: ''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. * Exakte Größe: ''find -size 100c -ls'' * Mindestgröße: ''find -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. * Zwischen Mindest- und Maximalgröße: ''find -type f -size +64c -size -256c'' sucht nur nach Dateien, die zwischen 64 und 256 Bytes groß sind. ==== 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. * Änderungszeit in Tagen: ''find -mtime -365'' findet Dateien, die innerhalb der letzter 365 Tage geändert wurden (**m**odification **time**). * ''ctime'': **c**hange **time**, Zeitpunkt der Änderung des Status einer Datei (Name, Rechte), womit sich beispielsweise auch erstellte Dateien finden lassen. * ''atime'': **a**ccess **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. * Änderungszeit in Minuten: ''find -cmin -5'' * Im Vergleich zu einer bestimmten Referenzdatei: ''find -cnewer /path/rerefence.file'' ==== Sonstiges ==== * Leere Verzeichnisse und Dateien der Größe 0 finden: ''find -empty'' * Verzeichnistiefe: * Maximale Verzeichnistiefe: ''find -maxdepth 3'' sucht bis zum maximal dritten Unterverzeichnis * Minimale Verzeichnistiefe: ''find -mindepth 2'' sucht ab dem zweiten Unterverzeichnis * Alle Dateien eines Benutzers finden: ''find / -user '' ==== 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 [[find#logische_operationen|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: -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: * ''-ls'': Wie [[linux:find#groesse|weiter oben]] bereits erwähnt, wird so eine ausführlichere Ausgabe erzeugt. * ''-fprint '': Statt der Ausgabe in der Konsole werden die gefundenen Dateinamen in die Datei '''' geschrieben. * ''-execdir {} +'': 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. [[linux:find#pruefsumme_mit_execdir|Beispiel ''md5sum'' weiter unten]]). * ''-ok {} \;'': Wie ''-exec'', jedoch wird vor jeder Aktion um eine Bestätigung gefragt. * ''-okdir'': Wie eine Kombination aus ''-ok'' und ''-execdir''. ===== Anwendungsbeispiele ===== Einige konkretere Anwendungsbeispiele für ''find''. Erklärungen zu komplexeren Beispielen mit ''xargs'' und mehr können [[http://mywiki.wooledge.org/UsingFind#Actions_in_bulk:_xargs.2C_-print0_and_-exec_.2B-|hier]] gefunden werden. ==== Prüfsumme mit ''execdir +'' ==== Erstelle für alle komprimierten ''tar''-Archive eine MD5-Prüfsumme: find -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 ==== [[https://blog.sash.pw/2016/06/groesste-dateien-finden/|Finde die größten Dateien in einem Verzeichnis]], beginnend bei 20 MB, und sortiere sie nach der Größe: find -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 [[https://blog.sash.pw/2015/01/groesse-coredumps-mit-systemd-begrenzen/|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 } {{tag>linux find}}