
Ich möchte alle txt-, xls- und pdf-Dateien in einem Verzeichnis sowie dessen Unterverzeichnissen löschen. Alles andere möchte ich speichern.
find . -type f ! -iname '*.xml$,.png$,.jpeg$,.gif$,' -delete
das schien zu funktionieren, aber es löschte einige andere Dateien, die ich brauche. Wie kann ich das erreichen, ohne etwas anderes zu löschen?
Antwort1
Gehen Sie stattdessen folgendermaßen vor:
find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' -delete
Sie können auch reguläre Ausdrücke verwenden:
find . -type f -iregex '.*\.\(xml\|png\|jpeg\|gif\)$' -delete
Antwort2
Es gibt grundsätzlich vier Möglichkeiten, dieses Problem mit find anzugehen.
Methode Nr. 1 - Verwendung-delete
$ find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' -delete
Wie andere in diesem Q&A bereits erwähnt haben, ist diese Methode die schnellste und am wenigsten ressourcenintensivste. Zitat aus demOnline-Dokumente finden:
10.1.6 Verwenden der Aktion „-delete“
Die effizienteste und sicherste Methode zur Lösung dieses Problems ist die Verwendung der Aktion „-delete“:
find /var/tmp/stuff -mtime +90 -delete
Diese Alternative ist effizienter als alle
-exec' or
Aktionen von „-execdir“, da sie den Aufwand für das Aufspalten eines neuen Prozesses und die Verwendung vonexec' to run
„/bin/rm“ vollständig vermeidet. Sie ist normalerweise auch effizienter alsxargs' for the same reason. The file deletion is performed from the directory containing the entry to be deleted, so the
die Aktion „-delete“ und hat dieselben Sicherheitsvorteile wie die Aktion „-execdir“.Die Aktion „-delete“ wurde von der BSD-Betriebssystemfamilie eingeführt.
NOTIZ:Bei diesem Ansatz ist zu beachten, dass die Verwendung von -delete
auch den Schalter impliziert -depth
. Was bedeutet das? Hier ist ein Beispiel dafür, wie -delete
Sie sich die Finger verbrennen können, wenn Sie nicht aufpassen.
Angenommen, ich habe ein Subversion-Arbeitsverzeichnis, in dem ich einige Dateien bereinigen möchte, die .svn-Unterverzeichnisse jedoch unverändert lassen möchte. Dazu könnte ich den folgenden Befehl verwenden:
$ find . -not "(" -name .svn -type d -prune ")" -type f -print
./a.txt
Da jedoch -delete
ein -depth
Schalter enthalten ist, werden die Dateien, die tatsächlich behandelt werden, wie folgt angezeigt:
$ find . -not "(" -name .svn -type d -prune ")" -type f -print -depth
./.svn/all-wcprops
./.svn/entries
./.svn/format
./.svn/text-base/a.txt.svn-base
./a.txt
Aus diesem Grund ist bei der Verwendung -delete
Vorsicht geboten.
Methode Nr. 2 --exec command {} +
$ find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' -exec rm {} \+
Im Vergleich zur -delete
Methode ist dies in Bezug auf Leistung und Portabilität zwischen Unixen höchstwahrscheinlich die nächstbeste Option. Die -exec ... {} +
Notation funktioniert wie folgt:
von der Find-Manpage
Diese Variante der Aktion -exec führt den angegebenen Befehl für die ausgewählten Dateien aus, die Befehlszeile wird jedoch erstellt, indem jeder ausgewählte Dateiname am Ende angehängt wird. Die Gesamtzahl der Aufrufe des Befehls ist viel geringer als die Anzahl der übereinstimmenden Dateien. Die Befehlszeile wird auf die gleiche Weise erstellt wie xargs seine Befehlszeilen erstellt. Innerhalb des Befehls ist nur eine Instanz von `{}' zulässig. Der Befehl wird im Startverzeichnis ausgeführt.
Tatsächlich funktioniert diese Methode also ähnlich wie xargs
, aber ohne dass man sich durch die Reifen springen muss, um die Ausgabe einer Suche durch eine Pipe an weiterzuleiten xargs
.
Methode Nr. 3 -xargs
$ find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' -print0 | xargs -0 rm -f
Es find ... -print0
wird eine Liste von Dateien erstellt, die den angegebenen Kriterien entsprechen. Diese Liste wird dann durch die Pipe an weitergegeben xargs
. Der -print0
Schalter fügt zwischen jedem Ergebnis von find ein ASCII-NUL-Zeichen als Trennzeichen ein. Der -0
Schalter on xargs
lässt es annehmen, dass die weitergegebenen Dateien durch ASCII-NUL-Zeichen getrennt sind.
Verglichen mit den Methoden Nr. 1 und Nr. 2 weist diese Methode eine ähnliche Leistung wie Nr. 2 auf, der -print0
Schalter wird jedoch nicht von allen Unix-Systemen universell unterstützt.
Methode Nr. 4 --exec command {} \;
$ find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' | exec rm -f {} \;
Im Vergleich zu den ersten drei Methoden ist dies die Methode mit der geringsten Leistung. Sie ruft den rm
Befehl buchstäblich für jede einzelne Datei auf, die der find
Befehl findet.
Weitere Überlegungen zur Sicherheit
Bei der Verwendung der oben genannten Methoden ist es vielleicht nicht so offensichtlich, dass einige Methoden sicherer sind als andere. Sie fragen sich wahrscheinlich: … Sicherheit? … was? Hier ist ein Beispiel.
Gehen Sie von Ihrem Root-Zugriff aus und führen Sie den folgenden Befehl aus:
$ find /var/tmp/somedir -type f -exec rm {} \;
Ohne Ihr Wissen hat jemand in böswilliger Absicht einen Link zum /etc
Verzeichnis unter erstellt /var/tmp/somedir
. Wenn der obige Befehl ausgeführt wird, /etc
wird das Verzeichnis ebenfalls gelöscht. Dieses Problem besteht bei allen Methoden zum Löschen von Dateien, mit Ausnahme der -delete
Option (Methode Nr. 1).
kurz und knapp;
Der schnellste und sicherste Weg, Dateien mithilfe von find zu löschen, ist die Verwendung von -delete
. Die Verwendung von xargs -0
kann eine ähnliche Leistung aufweisen, ist aber nicht so sicher. Die -delete
Aktion ist nicht vollständig portierbar. Die effizienteste portable Alternative ist -exec ... +
, aber diese ist unsicher und wird von Versionen von GNU findutils vor 4.2.12 nicht unterstützt.
Verweise
Antwort3
Es gibt eine kleine Ungenauigkeit inSLM-Antwort.
HINWEIS & Haftungsausschluss: das muss ein Kommentar sein zuSLM-Antwortaber im Moment kann ich noch keine Kommentare abgeben.
Das Beispiel "jemand hat in böswilliger Absicht einen Link erstellt" inWeitere Überlegungen zur Sicherheitist sowohl bei Unix-Hardlinks als auch bei Unix-Softlinks nicht ganz genau.
Um den Unterschied zwischen den beiden zu verstehen, lesen Sie bitteHardlink und symbolische Links in Unixoder google es.
Für Softlinks (die am häufigsten verwendete Art) GNU find
sowohlBDS find
nichtfolge symbolischen Links, es sei denn, es wird ein spezielles -L
Flag verwendet, um das Folgen symbolischer Links zu erzwingen. [Siehe man find
]
Dieses Beispiel ist also wahrscheinlich kein Problem, es sei denn, SieGewalt find
Softlinks mithilfe der -L
Flagge zu folgen. Dies ist sowieso die gefährliche Wahl.
Bei Hardlinks find
folgt der Link zueine andere DateiBeachten Sie jedoch, dass harte Links zu einemein anderes Verzeichnis„wird wahrscheinlich fehlschlagen“, siehe into man ln
für GNU ln
:
-d, -F, --directory
allow the superuser to attempt to hard link directories (note: will probably
fail due to system restrictions, even for the superuser)
Daher ist es wahrscheinlich überhaupt nicht möglich, einen Hardlink zu einem Verzeichnis zu erstellen, und es find
wird nichts folgen.
Beachten Sie, dass bei einigen BDS- ln
Implementierungen -d
überhaupt keine Option vorhanden ist.