TL; DR: Der beste Weg ist, -exec rmstatt zu verwenden -delete.
find a \( -name b -prune \) -o -type f -exec rm {} +
Erläuterung:
Warum beschwert sich find, wenn Sie versuchen, -deletemit zu verwenden -prune?
Kurze Antwort: weil -deleteimpliziert -depthund unwirksam -depthmacht -prune.
Bevor wir zur langen Antwort kommen, beobachten Sie zunächst das Verhalten des Findens 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 Bestellung in einem einzigen Verzeichnis. Es besteht jedoch die Garantie, dass ein Verzeichnis vor seinem Inhalt verarbeitet wird. Beachten Sie foo/vor jedem foo/*und foo/barvor jedem foo/bar/*.
Dies kann mit umgekehrt werden -depth.
$ find foo/ -depth
foo/f2
foo/bar/b2
foo/bar/b1
foo/bar
foo/f1
foo/
Beachten Sie, dass jetzt alle foo/*vorher erscheinen foo/. Gleiches gilt für foo/bar.
Längere Antwort:
-pruneverhindert, dass find in ein Verzeichnis absteigt. Mit anderen Worten, -pruneüberspringt den Inhalt des Verzeichnisses. In Ihrem Fall wird -name b -pruneverhindert, dass die Suche in ein Verzeichnis mit dem Namen absteigt b.
-depthmacht find, um den Inhalt eines Verzeichnisses vor dem Verzeichnis selbst zu verarbeiten. Das heißt, bis find den Verzeichniseintrag verarbeiten kann, ist bsein Inhalt bereits verarbeitet. Somit -pruneist -depthin der Tat unwirksam .
-deleteimpliziert, -depthdass zuerst die Dateien und dann das leere Verzeichnis gelöscht werden können. -deleteweigert sich, nicht leere Verzeichnisse zu löschen. Ich denke, es wäre möglich, eine Option hinzuzufügen, um -deletedas Löschen nicht leerer Verzeichnisse zu erzwingen und / oder zu verhindern -delete, dass dies impliziert wird -depth. Aber das ist eine andere Geschichte.
Es gibt noch einen anderen Weg, um das zu erreichen, was Sie wollen:
find a -not -path "*/b*" -type f -delete
Dies kann leichter zu merken sein oder auch nicht.
Dieser Befehl steigt immer noch in das Verzeichnis ab bund verarbeitet jede einzelne Datei darin nur -not, um sie abzulehnen. Dies kann ein Leistungsproblem sein, wenn das Verzeichnis sehr bgroß ist.
-pathfunktioniert anders als -name. -nameStimmt nur mit dem Namen (der Datei oder des Verzeichnisses) überein, während er -pathmit dem gesamten Pfad übereinstimmt. Beobachten Sie zum Beispiel den Weg /home/lesmana/foo/bar. -name -barwird übereinstimmen, weil der Name ist bar. -path "*/foo*"wird übereinstimmen, da sich die Zeichenfolge /fooim Pfad befindet. -pathhat einige Feinheiten, die Sie verstehen sollten, bevor Sie es verwenden. Lesen Sie die Manpage von findfü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 wird, überspringt alle Dateien, deren übergeordnetes Verzeichnis mit dem Namen beginnt b(positiv). Es wird jedoch auch jede Datei übersprungen, mit deren Namen bunabhängig von der Position im Baum begonnen wird (falsch positiv). Dies kann behoben werden, indem ein besserer Ausdruck als geschrieben wird "*/b*". Das bleibt als Übung für den Leser.
Ich gehe davon aus, dass Sie aund bals Platzhalter verwendet haben und die richtigen Namen eher wie allosaurusund sind brachiosaurus. Wenn Sie brachiosaurusanstelle von setzen, bwird die Anzahl der falsch positiven Ergebnisse drastisch reduziert.
Zumindest die Fehlalarme werden nicht gelöscht, so dass es nicht so tragisch ist. Darüber hinaus können Sie nach Fehlalarmen suchen, indem Sie zuerst den Befehl ohne ausführen -delete(aber denken Sie daran, das implizite zu platzieren -depth) und die Ausgabe untersuchen.
find a -not -path "*/b*" -type f -depth
aaußer eina/b?