Ich möchte rekursiv alle Dateien löschen, auf die seit einiger Zeit im Ordner a
nicht zugegriffen wurde , mit Ausnahme aller Dateien im Unterordner b
.
find a ( -name b -prune ) -o -type f -delete
Allerdings bekomme ich eine Fehlermeldung:
find:Die Aktion -delete schaltet automatisch -Tiefe ein, aber -prune tut
nichts, wenn -Tiefe aktiv ist. Wenn Sie trotzdem weitermachen wollen,
verwenden Sie einfach explizit die Option -depth.
Hinzufügen von -depth
bewirkt alle Dateien in b
enthalten sein, was nicht darf passieren.
Kennt jemand einen sicheren Weg, um dies zum Laufen zu bringen?
Akzeptierte Antwort:
Eine Möglichkeit ist die Verwendung von -exec rm
statt -delete
.
find a ( -name b -prune ) -o -type f -exec rm {} +
verwenden Sie alternativ -not -path
statt -prune
:
find a -not -path "*/b*" -type f -delete
Erklärung warum -prune
kollidiert mit -delete
:
finden Sie Beschwerden, wenn Sie versuchen, -delete
zu verwenden mit -prune
weil -delete
impliziert -depth
und -depth
macht -prune
unwirksam.
beobachten Sie das Verhalten von find mit und ohne -depth
:
$ find foo/
foo/
foo/f1
foo/bar
foo/bar/b2
foo/bar/b1
foo/f2
Es gibt keine Garantie für die Reihenfolge in einem einzelnen Verzeichnis. Aber es gibt eine Garantie, dass ein Verzeichnis vor seinem Inhalt verarbeitet wird. Beachten Sie foo/
vor jedem foo/*
und foo/bar
vor jedem foo/bar/*
.
Dies kann mit -depth
umgekehrt werden .
$ find foo/ -depth
foo/f2
foo/bar/b2
foo/bar/b1
foo/bar
foo/f1
foo/
Beachten Sie, dass jetzt alle foo/*
vor foo/
erscheinen . Dasselbe gilt für foo/bar
.
weitere Erklärung:
-prune
verhindert, dass find in ein Verzeichnis absteigt. Mit anderen Worten-prune
überspringt den Inhalt des Verzeichnisses. In Ihrem Fall-name b -prune
bedeutet, dass wenn find ein Verzeichnis mit dem Namenb
erreicht es überspringt das Verzeichnis inklusive aller Unterverzeichnisse.-depth
bewirkt, dass find den Inhalt eines Verzeichnisses vor dem Verzeichnis selbst verarbeitet. Das heißt bis zu dem Zeitpunkt, an dem find den Verzeichniseintragb
verarbeitet sein Inhalt wurde bereits verarbeitet. Also-prune
ist bei-depth
wirkungslos in Kraft.-delete
impliziert-depth
so kann es zuerst den Inhalt und dann das leere Verzeichnis löschen.-delete
weigert sich, nicht leere Verzeichnisse zu löschen.
Erklärung der alternativen Methode:
find a -not -path "*/b*" -type f -delete
Dies kann einfacher zu merken sein oder auch nicht.
Dieser Befehl landet immer noch im Verzeichnis b
und verarbeitet jede einzelne Datei darin nur für -not
sie abzulehnen. Dies kann ein Leistungsproblem sein, wenn das Verzeichnis b
ist riesig.
-path
funktioniert anders als -name
. -name
stimmt nur mit dem Namen (der Datei oder des Verzeichnisses) überein, während -path
entspricht dem gesamten Pfad. Beachten Sie zum Beispiel den Pfad /home/lesmana/foo/bar
. -name bar
stimmt überein, da der Name bar
ist . -path "*/foo*"
stimmt überein, weil die Zeichenfolge /foo
liegt im Weg. -path
hat einige Feinheiten, die Sie verstehen sollten, bevor Sie es verwenden. Lesen Sie die Manpage von find
für weitere Details.
Beachten Sie, dass dies nicht 100% narrensicher ist. Es besteht die Möglichkeit von „false positives“. Die Art und Weise, wie der Befehl oben geschrieben ist, überspringt jede Datei, die ein übergeordnetes Verzeichnis hat, dessen Name mit b
beginnt (positiv). Aber es wird auch jede Datei überspringen, deren Name mit b
beginnt unabhängig von der Position im Baum (falsch positiv). Dies kann behoben werden, indem ein besserer Ausdruck als "*/b*"
geschrieben wird . Das bleibt dem Leser als Übung überlassen.
Ich nehme an, dass Sie a
verwendet haben und b
als Platzhalter und die echten Namen ähneln eher allosaurus
und brachiosaurus
. Wenn Sie brachiosaurus
setzen anstelle von b
dann wird die Menge an Fehlalarmen drastisch reduziert.
Zumindest werden die Fehlalarme nicht sein gelöscht, damit es nicht so tragisch wird. Außerdem können Sie auf Fehlalarme prüfen, indem Sie den Befehl zuerst ohne -delete
ausführen (Aber denken Sie daran, die implizite -depth
zu platzieren ) und untersuchen Sie die Ausgabe.
find a -not -path "*/b*" -type f -depth