Perché find con -delete ha cancellato i file nella mia directory / save / quando find senza delete non è stato in grado di individuarli?


20

Voglio eliminare tutti i file nella struttura di directory corrente, tranne quelli in save. Ho eseguito questo comando:

 find . \( -name save -prune \) -o -type f -ls | grep /save/

e non ne ha trovato nessuno. Ma quando ho eseguito questo comando:

 find . \( -name save -prune \) -o -type f -delete

Tutti quei file in / save / erano spariti. Cosa mi sto perdendo?


4
Ahi ... ho imparato qualcosa oggi (grazie a te). E raccomando un semplice mv save/ ../some/safer/locationprima di un comando di eliminazione "generico" (... ma ovviamente prima del tuo post avrei fatto lo stesso controllo e mi sarei imbattuto nello stesso problema!). Ora vai a cercare un buon "undelete" per il filesystem su cui si trovavano i file ^^
Olivier Dulac,

3
Il mio dolore è la tua prevenzione.
Otheus,

1
1000 grazie a te. Il codice (spesso?) Funziona in modo misterioso ...
Olivier Dulac il


@lesmana Ho votato la tua risposta lì. purtroppo, la mia versione di find non mi dà un così bel avvertimento :(
Otheus

Risposte:


26

-deleteimplica -depthche non funziona -prune( -depthinizia con le foglie). C'è un avvertimento al riguardo nel manuale della versione GNU ( -deleteè un'estensione di FreeBSD ora supportata anche da GNU finde da alcune altre implementazioni).

info find --index-search=-delete

L'uso dell'azione '-delete' sulla riga di comando attiva automaticamente l'opzione '-depth' (* nota trova espressioni: :). Questo può essere sorprendente se in precedenza stavi solo testando con '-print', quindi di solito è meglio ricordare di usare esplicitamente '-depth'.

info find --index-search=-prune

Poiché "-delete" implica "-depth", l'uso di "-prune" in combinazione con "-delete" può comportare la cancellazione di più file di quanto previsto.

Qui hai la possibilità di utilizzare rminvece:

find . -name save -prune -o -type f -exec rm -f {} +

(potenzialmente non sicuro se ci sono directory scrivibili da altri là dentro, in quanto si potrebbe farti eliminare i file al di fuori della struttura di directory corrente sostituendo le directory con collegamenti simbolici mentre si esegue quel comando).

Un'alternativa più sicura:

find . -name save -prune -o -type f -execdir rm -f -- {} \;

Ciò non ha il problema sopra menzionato ma significa eseguirne uno rmper file. Il --è necessario per l'attuazione di FreeBSD, e non la GNU quella che i nomi di file prefissi con ./.

In alternativa, come suggerito da Costas:

LC_ALL=C find . ! -name save ! -path '*/save/*' -type f -delete

(ma che ancora inutilmente scende nelle savedirectory)

Il LC_ALL=Cc'è così *corrisponde a qualsiasi sequenza di byte (anche quelli che non formano caratteri validi nella localizzazione corrente). Notare che influirà sulla lingua dei messaggi di errore (inglese anziché sulla lingua dell'utente).


Qual è il problema di sicurezza qui con rm?
jrw32982 supporta Monica il

@ jrw32982, vedi modifica con collegamento al manuale di ricerca GNU
Stéphane Chazelas,
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.