Come eliminare le directory in base all'output di `find`?


148

Emetto il seguente comando per trovare le directory .svn:

find . -name ".svn"

Questo mi dà i seguenti risultati:

./toto/.svn
./toto/titi/.svn
./toto/tata/.svn

Come posso elaborare tutte queste righe rm -frper eliminare le directory e il loro contenuto?


3
GNU find ha l' -deleteopzione.
Marco,

5
Oppure puoi aggiungere -exec rm -r "{}" \;alla fine della ricerca - fai attenzione quando lo usi rm -r! :)
Drav Sloan,

10
@Marco L'opzione di eliminazione non sembra funzionare su directory.
Arnaud,

@SuperChafouin Funziona perfettamente qui su file e directory. Il punto è che elimina solo le directory emtpy e quando lo specifichi -name ".svn"corrisponde solo alla .svndirectory stessa e non ai file che si trovano nella .svndirectory.
Marco,

1
@SuperChafouin ma non funzionerà per i percorsi con spazi (quindi usando -exectra virgolette "{}").
Drav Sloan,

Risposte:


195

Trova può eseguire argomenti con l' -execopzione per ogni corrispondenza trovata. È un meccanismo consigliato perché è possibile gestire correttamente percorsi con spazi / newline e altri caratteri. Dovrai eliminare il contenuto della directory prima di poter rimuovere la directory stessa, quindi usa -ril rmcomando per ottenere questo.

Per il tuo esempio puoi emettere:

find . -name ".svn" -exec rm -r "{}" \;

Puoi anche dire a find di trovare solo le directory chiamate .svn aggiungendo un -type dsegno di spunta:

find . -name ".svn" -type d -exec rm -r "{}" \;

Avvertenza Usare rm -rcon cautela elimina la cartella e tutto il suo contenuto.

Se si desidera eliminare solo directory vuote e directory che contengono solo directory vuote, find può farlo da solo con -deletee -empty:

find . -name ".svn" -type d -empty -delete

22
Ho visto consiglio di correre sempre -type dopo -name nei comandi find, dal momento che le chiamate verso statper ottenere il tipo sono costosi. L'ho provato da solo su un mucchio di file abbastanza grande, e sembra essere vero: la corsa find . -name 'foo' -type dha richiesto 19 secondi, mentre find . -type d -name 'foo'32 secondi. Quindi circa il 50% di tempo in più per essere eseguito per -typeprimo.
spinup

6
uso questo comando da anni, ma su Mac ora ricevo errori dicendo che quelle directory non esistono. Anche se li cancella. Non ho mai visto messaggi prima.
Chovy

1
Lo stesso di @chovy. C'è un modo per sbarazzarsi di questi messaggi?
Clément,

2
@chovy @ clément Questo perché findvuole vedere in quella cartella per altre partite, mentre allo stesso tempo rimuove la cartella. ~ Non so ancora come risolvere questo problema. ~ Correzione sporca:find . -name "folder-to-delete" -print0 | xargs -r0 -- rm -r
Charlie

5
@chovy @ Clément Penso che l' -depthargomento find . -depth -name ".svn" -type d -exec rm -r "{}" \;
risolva

67

Ecco un portatile ancora più veloce del modo di risposta accettato.

L'uso +di un punto e virgola come findterminatore di comando sta ottimizzando l'utilizzo della CPU. Questo può essere significativo se hai molte .svnsottodirectory:

find . -name .svn -type d -exec rm -rf {} +

Si noti, inoltre, che non hai mai 1 necessità di citare le parentesi graffe qui.

1 A meno che non si usi la fishshell.


5
Qual è la differenza tra + e punto e virgola? Perché non usiamo le parentesi graffe?
Shicheng Guo,

1
@ShichengGuo Con il punto e virgola, verrà trovato un comando rm per directory, con il + un singolo comando rm elaborerà tutte le directory trovate (o almeno un numero molto grande di esse.) Non capisco la tua seconda domanda, riccia le parentesi graffe vengono utilizzate qui.
jlliagre,

Penso che @ ShichengGuo significhi perché non abbiamo bisogno di citare qui le parentesi graffe (@jlliagre ha scritto che non abbiamo mai bisogno di citarle). Non riesco a trovare un riferimento ora, ma capisco perché trova automaticamente sfuggirà ai percorsi sostituiti per {}.
Quinn Comendant

La risposta e la domanda non sono del tutto giuste su cosa fa +. Se vengono trovati molti file, allora ';' darebbe l'errore "linea di comando troppo lunga". + suddivide i file trovati in batch che sono inferiori alla lunghezza massima consentita della riga di comando ed esegue il comando per ciascun batch.
sabato

1
@gaoithe Ho eseguito il rollback della modifica che ha sostituito un'istruzione corretta con un'errata. Utilizzando + non ridurre l'utilizzo della CPU, utilizzo ; non portare ad un comando troppo lungo errore.
jlliagre,

27

Supponiamo che tu stia usando gnu find , puoi usare l' -deleteopzione:

find . -name test -delete

che è più facile da ricordare.


Valuta di espandere il tuo post con una spiegazione del comando (o della documentazione per il backup della soluzione). Spesso una (o due) risposte di riga non sono le più illuminanti.
HalosGhost

94
Questo non funziona su directory non vuote.
Belacqua,

2
funziona anche su Mac OS X
disegna il

Questo non funziona per le cartelle non vuote ma è la soluzione più semplice e sicura
RousseauAlexandre

L'ordine delle opzioni è molto importante, trova li eseguirà in ordine, quindi, l'eliminazione deve essere l'ultima
Jose Ignacio Centeno

13

Sul mio computer quando utilizzo:

find . \( -name dirname -type d \) -exec rm -r '{}' ';'

Le directory vengono eliminate ma viene visualizzato l'errore:

find: ‘./dirname’: No such file or directory

per ogni directory.

Le mie directory non sono vuote, quindi l'opzione -delete non funzionerà per me. Ho trovato il motivo di questo comportamento qui :

  1. find accetta (non necessariamente) la prima voce nella directory ./. questo sarebbe ad esempio dir.1 /
  2. lo confronta con il modello 'dir.?'. corrisponde? sì.
  3. find esegue "rm -r dir.1".
  4. find tenta di inserire dir.1 / per trovare il modello all'interno della directory. non sa nulla del comando exec.
  5. non trova più dir.1 /. restituisce ENOENT (guarda l'output di strace)

Ho usato questo invece per aggirare:

rm -r `find . -name dirname -type d`

Tieni presente che find tenterà comunque di ricorrere in directory denominate dirname, il che non è realmente necessario e richiederà del tempo aggiuntivo. A seconda della struttura della directory, potresti essere in grado di aggirare questo problema con l' --depthopzione find. Inoltre, se si dispone di una struttura di directory come dirname / foo / dirname, si otterranno errori "No such file or directory" da rm. Per eliminare gli errori puoi reindirizzare stderr su / dev / null o usare il -fflag (force) con rm.


2
Cattiva idea: il nome del file con spazi causerà ogni sorta di problemi orribili
Clément,

2
Per i futuri lettori: find . -name "to-delete" -print0 | xargs -r0 -- rm -rè una versione a prova di errore che non si schianta sugli spazi
Charlie

3
Vedi unix.stackexchange.com/a/115869/8257 che devi aggiungere -prune.
Mapio

1
Aggiungi -pruneper evitare l'errore "Nessun file o directory".
Julien Carsique,

12

Un modo più veloce per farlo è:

find . -name ".svn" -type d -prune -exec rm -rf '{}' '+'

Nel caso in cui tu abbia ".svn" dentro un altro ".svn".


Non è molto utile se si desidera trovare le directory da eliminare con le directory secondarie.
Alexis Wilke,

5

Soluzione specifica per Bash:

shopt -s globstar
rm -r **/.svn
shopt -u globstar #optional. this will disable globstar expansion

3
Nota per l'espansione della riga di comando di globs che corrispondono a molti file, esiste un limite al numero di file che è possibile abbinare a questo meccanismo. Il superamento di questo limite comporteràbash: /bin/rm: Argument list too long
Drav Sloan il

1
@DravSloan è corretto, ma quel limite è nelle centinaia di migliaia di file. È qualcosa da tenere a mente, ma probabilmente non sarà un problema per la maggior parte delle persone.
evilsoup,

4

Ho scoperto che l' -deleteazione funziona bene con il -pathtest. Ad esempio, i seguenti dovrebbero funzionare sul problema dei poster originali:

find . -path '*/.svn*' -delete

Sei sicuro? -deleteimplica -depthe sicuramente cancella le directory non vuote sul mio sistema.
Magnus,

Testato nuovamente e funziona. Forse è stato solo un refuso che ho corretto.
Kenorb,

Ho anche provato questo approccio e ha funzionato: le directory sono state eliminate.
Allan,
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.