Löschen Sie Dateien und Verzeichnisse anhand ihrer Namen. Keine übereinstimmende Datei oder Ordner

32

Ich muss alle zusammengestellten Daten löschen:

  • Verzeichnisse genannt build,
  • Verzeichnisse genannt obj,
  • * .so Dateien.

Ich habe einen Befehl geschrieben

find \( -name build -o -name obj -o -name *.so \) -exec rm -rf {} \;

das geht alle verzeichnisse rekursiv durch und löscht alles was ich brauche.

Warum habe ich so eine Ausgabe am Ende? Vielleicht sollte ich einen anderen Befehl schreiben.

find: `./3/obj': No such file or directory
find: `./3/build': No such file or directory
find: `./1/obj': No such file or directory
find: `./1/build': No such file or directory
find: `./2/obj': No such file or directory
find: `./2/build': No such file or directory
Maksim Dmitriev
quelle
Auf welchem ​​System bist du? Sie sollten immer so verwenden, finddas find /search_directory optionsAuslassen des Suchverzeichnisses ist keine gute Idee
Kiwy
Ein automatisiertes Löschen wie dieses ist keine gute Idee. Sie könnten sich von einem Skript Kandidaten geben lassen, die Sie sich dann ansehen sollten, um sicherzustellen, dass Sie nichts Wichtiges oder Notwendiges im System löschen. Sie sind nicht explizit, wo Sie dies ausführen. Wenn Sie dies nur in einem Benutzerbereich tun, kann es wahrscheinlich nicht viel schaden, aber Sie sollten sicherstellen, dass Sie dies nicht versehentlich in einem Systembereich tun. Sie möchten auf jeden Fall ein solches Skript als Benutzer ausführen.
Faheem Mitha
@ Kiwy, @ FaheemMitha, der Befehl wird nur in der Projektdirektion verwendet. es wird dort keinen Schaden anrichten.
Maksim Dmitriev

Antworten:

54

Verwenden -pruneSie diese Option für die Verzeichnisse, die Sie trotzdem löschen möchten, um findzu vermeiden, dass Sie versuchen, Dateien in ihnen zu finden:

find . \( -name build -o -name obj -o -name '*.so' \) -prune -exec rm -rf {} +

Beachten Sie auch, dass *.soin Anführungszeichen gesetzt werden muss, da es sonst von der Shell zur Liste der .soDateien im aktuellen Verzeichnis erweitert werden kann.

Das Äquivalent Ihres GNU- -regexTyps wäre:

find . \( -name build -o -name obj -o -name '*?.so' \) -prune -exec rm -rf {} +

Beachten Sie, dass Sie, wenn Sie GNU-spezifische Syntax verwenden, auch -deleteanstelle von verwenden können -exec rm -rf {} +. Mit -deleteGNU findschaltet -depthautomatisch ab . Auf diese Weise werden keine externen Befehle ausgeführt. Dies ist effizienter und sicherer, da dadurch die Race-Bedingung beseitigt wird, bei der Sie möglicherweise in der Lage sind, die falschen Dateien zu entfernen, indem zwischenzeitlich ein Verzeichnis in einen Symlink geändert wird findfindet eine Datei und rmentfernt sie (siehe info -f find -n 'Security Considerations for find'für Details).

find . -regextype posix-egrep -regex '.*/((obj|build)(/.*)?|.+\.so)' -delete
Stéphane Chazelas
quelle
-deletebehandelt auch Dinge wie Leerzeichen besser
Izkata
@Izkata, nicht besser als das, -exec rm -rf {} +was mit denen auch kein Problem hat.
Stéphane Chazelas
@StephaneChazelas - Ich bin verwirrt über {}- sollten sie zitiert werden oder nicht? Es scheint ohne Anführungszeichen zu funktionieren, aber GNU Findutils Manual verwendet '{}'in Beispiel. Kannst du das bitte klären?
Grebneke
1
@grebneke, ich denke, es gibt irgendwo einen Beitrag, in dem Ansprüche in sehr alten Versionen von Zitaten erforderlich sein könnten csh, aber ich konnte diesen Anspruch nie verifizieren. Sie werden in keiner modernen Shell benötigt, die ich kenne. Sie werden von POSIX definitiv nicht benötigt. In den POSIX-Beispielen werden sie nicht verwendet.
Stéphane Chazelas
3
Und -deletekann nicht mit Verzeichnissen verwendet werden.
16.
8

Ich denke, der Grund dafür ist, dass zuerst findder Verzeichnisbaum gelöscht wird und versucht wird, den Verzeichnisinhalt zu überprüfen, was offensichtlich nicht die bestmögliche Reihenfolge ist. Sie können finddie Überprüfung des Inhalts erzwingen :

find . -depth ...

Sie sollten die Verwendung -deletefür Dateien und -exec rmdirfür Verzeichnisse in Betracht ziehen .

Hauke ​​Laging
quelle
0

Meine Lösung.

find . -regextype posix-egrep -regex ".*/(obj|build|.+\.so)" -prune -exec rm -rf {} +

+ vs \; im Befehl -exec

Maksim Dmitriev
quelle
Das wird nicht immer funktionieren, nur wenn in einem gelöschten Verzeichnis keine Grenze zwischen den Ausführungen besteht.
Gilles 'SO- hör auf böse zu sein'
@ Gilles, was bedeutet "Grenze zwischen Hinrichtungen"?
Maksim Dmitriev
1
-exec … {} +Führt den Befehl für mehrere Dateien gleichzeitig aus, so viele wie in die Befehlszeile passen. Wenn zu viele Dateien vorhanden sind (oder genauer gesagt, wenn die Gesamtlänge der Pfade zu lang ist), findwerden mehrere Instanzen von ausgeführt rm, und daher wird möglicherweise ein Verzeichnis entfernt, das gerade durchsucht wird. Es ist nur weniger wahrscheinlich mit +als mit ;, aber +es löst das Problem nicht.
Gilles 'SO- hör auf böse zu sein'