Perché 'find -delete' cancella ricorsivamente tutti i file in una directory


15

Quindi il seguente comportamento di unix find mi è costato caro:

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

Come può aver senso questo?


2
Questa domanda è correlata, potrebbe essere interessante per i futuri lettori. unix.stackexchange.com/questions/101282/…
Bernhard,

Risposte:


14

La riga di comando di find è composta da diversi tipi di opzioni, che sono combinate per formare espressioni.

L' findopzione -deleteè un'azione.
Ciò significa che viene eseguito per ogni file abbinato finora.
Come prima opzione dopo i percorsi, tutti i file sono abbinati ... oops!

È pericoloso - ma la pagina man ha almeno un grosso avvertimento :

Da 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.


Da più avanti 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.


Nel provare cosa findfarà un comando:

Per vedere come piace un comando

find . -name '*ar' -delete

verrà eliminato, è possibile innanzitutto sostituire l'azione -deletecon un'azione più innocua, ad esempio -flso -print:

find . -name '*ar' -print

Questo stamperà quali file sono interessati dall'azione.
In questo esempio, -print può essere lasciato fuori. In questo caso, non v'è l'azione a tutti, quindi si aggiunge la più ovvia implicitamente: -print. (Vedi il secondo paragrafo della sezione "EXPRESSIONS" citata sopra)


Immagino di essere stato solo un idiota per non aver letto prima il manuale .. Ma è sembrato così semplice aggiungere la -deletebandiera :-) Ma c'è qualche motivo per cui qualcuno vorrebbe mai fare find . -deletepiuttosto che rm -rf .? O capita che questo sia il modo in cui findanalizza ed elabora i suoi argomenti?
mszep

1
Oh, sono pienamente d'accordo sul fatto che la sintassi è molto pericolosa , ma è difficile da evitare, in quanto è solo un caso speciale della sintassi dell'espressione della linea comune di find, che è estremamente potente. Potente come in " Una potente motosega ".
Volker Siegel,

la pagina del manuale citato non dice warning: use -depth when testing stuff you later want to -deletecosa non hai fatto nel tuo esempio pratico di lato?
pqnet,

Oh, giusto - il problema è il titolo - intendevo illustrare l'uso della stampa al posto di -delete come -nun'opzione; Il primo comando non dovrebbe avere alcun uso pratico, ovviamente; Vado a cambiarlo.
Volker Siegel,

9

Nell'ordine degli findargomenti conta molto.

Gli argomenti possono essere opzioni, test e azioni. In genere è necessario utilizzare prima le opzioni, quindi i test, quindi le azioni.

A volte findti avverte persino di un possibile cattivo ordinamento (ad esempio quando usi -maxdepthdopo altri argomenti), ma altri sembra che non lo faccia.

Quello che find . -delete -name '*ar'fa è:

  1. Trova file e directory nella directory corrente.
  2. Li elimina TUTTI così come sono stati trovati!
  3. Quindi vede se sono chiamati come '* ar' (questa parte non ha alcun effetto ora).

Quello che probabilmente vuoi fare è:

find -name '*ar' -delete

Questo, per ogni file, vedrà se corrisponde '*ar', e solo se soddisfa la condizione eliminerà il file.

Scusa se l'hai scoperto troppo tardi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.