Warum löscht 'find -delete' alle Dateien in einem Verzeichnis rekursiv?


15

Also das folgende Verhalten von Unix kostet mich nur teuer:

> touch foo
> touch bar
> ls  
bar  foo
> find . -name '*oo' -delete
> ls
bar
> touch baz
> ls
bar  baz
> find . -delete -name '*ar'
> ls
> #WHAAAT?

Wie macht das Sinn?


2
Diese Frage ist verwandt, könnte für zukünftige Leser interessant sein. unix.stackexchange.com/questions/101282/…
Bernhard

Antworten:


14

Die Befehlszeile von find besteht aus verschiedenen Arten von Optionen, die zu Ausdrücken kombiniert werden.

Die findOption -deleteist eine Aktion.
Das heißt, es wird für jede Datei ausgeführt, die bisher abgeglichen wurde.
Als erste Option nach den Pfaden werden alle Dateien abgeglichen ... Hoppla!

Es ist gefährlich - aber die Manpage hat zumindest eine große Warnung :

Von man find:

ACTIONS
    -delete
           Delete  files; true if removal succeeded.  If the removal failed, an
           error message is issued.  If -delete fails, find's exit status  will
           be nonzero (when it eventually exits).  Use of -delete automatically
           turns on the -depth option.

           Warnings: Don't forget that the find command line is evaluated as an
           expression,  so  putting  -delete first will make find try to delete
           everything below the starting points you specified.  When testing  a
           find  command  line  that  you later intend to use with -delete, you
           should explicitly specify -depth in order to avoid later  surprises.
           Because  -delete  implies -depth, you cannot usefully use -prune and
           -delete together.


Von weiter oben in man find:

EXPRESSIONS
    The expression is made up of options (which affect overall operation rather
    than  the  processing  of  a  specific file, and always return true), tests
    (which return a true or false value), and actions (which have side  effects
    and  return  a  true  or false value), all separated by operators.  -and is
    assumed where the operator is omitted.

    If the expression contains no actions other than  -prune,  -print  is  per‐
    formed on all files for which the expression is true.


Beim Ausprobieren, was ein findBefehl bewirkt:

Um zu sehen, wie ein Befehl aussieht

find . -name '*ar' -delete

löschen, können Sie die Aktion zuerst -deletedurch eine harmlosere Aktion ersetzen - wie -flsoder -print:

find . -name '*ar' -print

Dadurch wird gedruckt, welche Dateien von der Aktion betroffen sind.
In diesem Beispiel kann der -print weggelassen werden. In diesem Fall gibt es keine Maßnahmen überhaupt, so die naheliegendste implizit hinzugefügt wird: -print. (Siehe den zweiten Absatz des oben genannten Abschnitts "AUSDRÜCKE")


Ich schätze, ich war nur ein Idiot, weil ich das Handbuch nicht zuerst gelesen habe. Aber es schien so einfach, nur die -deleteFlagge hinzuzufügen :-) Aber gibt es einen Grund, den irgendjemand jemals find . -deletelieber tun würde als rm -rf .? Oder ist das nur die Art findund Weise, wie Argumente analysiert und verarbeitet werden?
mszep

1
Oh, ich stimme voll und ganz zu, dass die Syntax sehr gefährlich ist - aber das ist schwer zu vermeiden, da es sich nur um einen Sonderfall der Kommandozeilen-Ausdruckssyntax von find handelt, die extrem leistungsfähig ist. Kraftvoll wie in " Eine kraftvolle Kettensäge ".
Volker Siegel

heißt es nicht auf der zitierten Handbuchseite, warning: use -depth when testing stuff you later want to -deletewas Sie in Ihrem praktischen Beispiel nicht getan haben?
pqnet

Oh, richtig - das Problem ist die Überschrift - ich wollte die Verwendung von Print anstelle von -delete wie eine -nOption veranschaulichen ; Der erste Befehl sollte natürlich überhaupt keinen praktischen Nutzen haben; Ich werde es ändern gehen.
Volker Siegel

9

In der findArgumentationsreihenfolge zählt viel.

Argumente können Optionen, Tests und Aktionen sein. In der Regel sollten Sie zuerst Optionen, dann Tests und dann Aktionen verwenden.

Manchmal werden Sie findsogar vor einer möglichen Fehlbestellung gewarnt (zum Beispiel, wenn Sie -maxdepthnach anderen Argumenten suchen), bei anderen scheint dies jedoch nicht der Fall zu sein.

Was find . -delete -name '*ar'macht ist:

  1. Findet Dateien und Verzeichnisse im aktuellen Verzeichnis.
  2. Löscht sie ALLE, sobald sie gefunden wurden!
  3. Dann wird geprüft, ob sie den Namen '* ar' haben (dieser Teil hat jetzt keine Wirkung).

Was Sie wahrscheinlich tun möchten, ist:

find -name '*ar' -delete

Dadurch wird für jede Datei geprüft, ob sie übereinstimmt '*ar', und nur, wenn die Bedingung erfüllt ist, wird die Datei gelöscht.

Entschuldigung, wenn Sie es zu spät herausgefunden haben.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.