Rimuovi alberi di directory vuoti (rimuovendo quante più directory possibili ma nessun file)


12

Supponiamo che io abbia un albero dir come questo:

ROOTDIR
    └--SUBDIR1
        └----SUBDIR2
            └----SUBDIR3

Sto cercando un comando tale che quando inserisco:

$ [unknown command] ROOTDIR

L'intero albero dir può essere eliminato se non ci sono file ma solo dir all'interno dell'intero albero . Tuttavia, dire se esiste un file chiamato hello.pdf in SUBDIR1:

ROOTDIR
    └--SUBDIR1
        └--hello.pdf
        └----SUBDIR2
            └----SUBDIR3

Quindi il comando deve eliminare solo SUBDIR2 e precedenti.


Risposte:


11

Alexis è vicino. Quello che devi fare è questo:

find . -type d -depth -empty -exec rmdir "{}" \;

Questo prima analizzerà l'albero delle directory fino a quando non trova la prima directory vuota, quindi la elimina. Rendendo così vuota la directory principale che verrà quindi eliminata, ecc. Questo produrrà l'effetto desiderato (lo faccio probabilmente 10 volte a settimana, quindi sono abbastanza sicuro che sia giusto). :-)


Perché è -depthnecessaria l'opzione? find . -type d -empty -exec rmdir "{}" \;dovrebbe anche funzionare .... giusto?
Abhishek,

4
Considera se hai un albero (solo directory) foo/bar/baz. A meno che tu non lo usi -depth, proverà a eliminarlo per fooprimo, fallirà e finirai per farlo foo/bardopo averlo eseguito.
20

1
Probabilmente un'alternativa è usare +invece di ;rimuovere in batch le directory. Dal momento che lo stai facendo in profondità, i bambini verranno comunque rimossi prima dei genitori (probabilmente dipende dalla tua versione di rmdir / bash e dipende dal fatto che rmdir non cancella le directory non vuote). Questo per me funziona bash su cygwin:mkdir -p a/b/c/d ; find a -depth -type d -exec rmdir {} +
idbrii

3
Gente, cercate la risposta molto più concisa di go2null qui sotto! Non riesco a capire perché SE dia priorità alle risposte accettate piuttosto che alle risposte con la maggior parte dei voti nel mostrare le risposte sotto la domanda. L'OP accetta la migliore risposta disponibile al momento della sua scelta, ma in seguito possono arrivare risposte molto migliori che la comunità vota, no? (Certo, questo è qualcosa per meta ...)
jamadagni,

questo non funziona per me. cancella solo la foglia più profonda (SUBDIR3 in questo caso)
Joey Baruch,

23
find ROOTDIR -type d -empty -delete

uguale a

find ROOTDIR -type d -depth -empty -exec rmdir "{}" \;

ma usa l'azione "-delete" integrata.

Nota che "-delete" implica "-depth".


Complimenti per la risposta più concisa usando l'eliminazione integrata di find! Sto aggiungendo questo ai miei programmi di utilità locali!
Jamadagni,

3

Vorrei provare questo:

find ROOTDIR -type d -depth -exec rmdir {} \;

1

Ecco alcuni requisiti prima di poterlo fare in sicurezza:

  1. rimuovere prima le sottodirectory e poi le directory di livello superiore, ovvero è necessario ordinare l'elenco delle directory o utilizzare il flag rmdir --parents
  2. avvia ROOTDIR sempre con / o ./ per evitare sorprese con i file che iniziano con -
  3. utilizzare l'elenco di directory terminato NUL per lavorare con i nomi di directory con spazi

Ecco come lo farei in shell:

find ./ROOTDIR -type d | sort -r | tr '\n' '\000' | xargs -0 rmdir --ignore-fail-on-non-empty

Se non ti dispiace per alcuni errori ridondanti, puoi semplicemente forzare la rimozione di tutte le directory con i genitori e non devi eseguire alcun ordinamento (non puoi ordinare le stringhe terminate NUL che aggiungono bisogno di tr)

find ./ROOTDIR -type d -print0 | xargs -0 rmdir --ignore-fail-on-non-empty --parents

Complimenti per la spiegazione dettagliata della tua risposta. Probabilmente avrei usato lo stesso approccio, fino a quando non avessi appreso delle -empty -deleteopzioni findnella risposta di @ go2null.
Davor Cubranic

0
rmdir $(find ROOTDIR -type d | sort -r)

5
Questo non funzionerà se uno dei nomi delle directory contiene spazi bianchi o caratteri globbing. In genere è una cattiva idea utilizzare la sostituzione dei comandi in un elenco di nomi di file. E 'soprattutto una cattiva idea con findperché findha un modo di fare l'elaborazione in modo pulito: find … -exec.
Gilles 'SO- smetti di essere malvagio' il

Grazie a Gilles per averlo sottolineato. @lanzz, di solito pubblicare solo un comando senza spiegare cosa fa (e in questo caso, le insidie) non è sufficiente. Aggiungi alla tua risposta.
n0pe

0

Vorrei fare questo:

find ROOTDIR -type d | xargs -0 -I {} rmdir {}
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.