Come rimuovo tutte le sottodirectory da una directory?


51

Questa domanda è una specie di fase II alla prima domanda che ho pubblicato qui

Ho una directory che contiene un sacco di sottodirectory, file .zip e altri file casuali non contenuti in una sottodirectory.

Vorrei che uno script da riga di comando rimuovesse tutte le sottodirectory dalla directory principale, ma conservasse tutti i file zip e i file sciolti che non appartengono ad alcuna sottodirectory. Tutte le sottodirectory hanno dei contenuti, quindi credo che dovrei forzare la loro cancellazione con il comando -f.

Quindi, fondamentalmente, un comando che si trova all'interno della directory principale (o della directory corrente), elimina tutte le cartelle al suo interno, ma mantiene tutti gli altri contenuti e file che non sono una cartella o contenuti in una cartella.

Comprendo che l'eliminazione di elementi dalla riga di comando richiede un'attenzione particolare, ma ho già preso tutte le precauzioni necessarie per eseguire il backup in remoto.

Risposte:


62

In BASH puoi usare la barra finale ( penso che dovrebbe funzionare in qualsiasi shell POSIX):

rm -R -- */

Nota --che separa le opzioni dagli argomenti e consente di rimuovere le voci che iniziano con un trattino, altrimenti dopo l'espansione dalla shell il nome della voce verrebbe interpretato come un'opzione da rm(lo stesso vale per molte altre utilità della riga di comando).

Aggiungere l' -fopzione se non si desidera che venga richiesta la conferma quando si eliminano file non scrivibili.

Si noti che per impostazione predefinita, le directory nascoste (quelle il cui nome inizia con .) verranno lasciate sole.

Un avvertimento importante: l'espansione */includerà anche collegamenti simbolici che alla fine si risolveranno in file di tipo directory . E a seconda rmdell'implementazione, rm -R -- thelink/eliminerà semplicemente il collegamento simbolico o (nella maggior parte di essi) eliminerà il contenuto della directory collegata in modo ricorsivo ma non quella directory stessa né il link simbolico.

Se si utilizza zsh, un approccio migliore sarebbe utilizzare un qualificatore glob per selezionare solo i file di tipo directory:

rm -R -- *(/) # or *(D/) to include hidden ones

o:

rm -R -- *(-/)

per includere collegamenti simbolici alle directory (ma poiché, questa volta, l'espansione non ha /s finali , è solo il collegamento simbolico che viene rimosso con tutte le rmimplementazioni).

Con bash, AT&T ksh, yashoppure zshpuoi fare:

set -- */
rm -R -- "${@%/}"

spogliare il finale /.


Bellissimo! Funziona perfettamente. Non mi ero reso conto che fosse così facile da fare. Ti dispiacerebbe elaborare su -r vs. -R e cosa fanno questi comandi? Grazie molto.
Evster,

-r, -R, --recursiveSono sinonimi che significa "directory rimuovere e il loro contenuto in modo ricorsivo".
peterph

puoi spiegare cosa - e * / fare?
anfibio

6
Puoi anche dire rm -R ./*/: evita anche problemi con i nomi dei trattini.
l0b0

1
Fai solo attenzione a non modificare l'ordine di * e /. rm -R - / * fa qualcosa di completamente diverso che potresti non voler accadere: |
ChrisOdney,

13

Oltre al modo jolly, puoi anche usare find(almeno GNU find) per fare questo:

find -mindepth 1 -maxdepth 1 -type d -print0 | xargs -0 rm -R

Come per le altre findrighe, è possibile eseguire la prima parte ( find -mindepth 1 -maxdepth 1 -type d) per visualizzare un elenco di directory che verranno rimosse.

Un'opzione più sicura è fare qualcosa del genere:

find -mindepth 1 -maxdepth 1 -type d -print0 | xargs -0 mv -i -t ../to-rm
# or
mv -i -t ../to-rm */
# or
mv -i */ ../to-rm

nessuno dei quali sposta tutto il contenuto ../to-rminvece di eliminarlo. Puoi verificare che abbia fatto quello che volevi, loro rm -Rfquella directory a tuo piacimento.


+1 per il "cestino della CLI" to-rme findche gestisce bene le directory che iniziano con un punto (oltre a qualsiasi altra fuga ingombrante). :)
peterph

Grazie per il consiglio. Mi piace l'idea di passare a una directory separata prima di eliminarla. Sto lavorando tramite Terminal su Mac OS X e credo che dovrei installare una specie di pacchetto GNU per usare i comandi -mindepth e -maxdepth, giusto?
Evster

@Evster non è sicuro se Mac OS X find li supporti. Immagino che Fink (è ancora in giro?) Potrebbe installare una ricerca che lo fa. Oppure potresti ometterli e quindi filtrare l'elenco dei file prodotti usando grep. Sicuramente usa l'opzione mv su questo, invece di rm.
derobert

4

Potresti voler creare uno script per alcuni di questi suggerimenti, in particolare rm -R -- */, e tenerlo nella cartella / usr / local / bin; o creane uno aliasnel tuo file ~ / .bashrc. Dal momento che è così facile digitare un comando e rompere il sistema - anche una singola lettera e / o l'ordine delle lettere può comportare conseguenze catastrofiche - questo servirebbe come una soluzione un po 'più robusta che dover digitare le diverse opzioni e argomenti ogni volta che vuoi svolgere questo compito.

Inoltre, potresti voler includere l' opzione -i or --interactive=onceo -I or --interactive=alwaysnel tuo script / comando che servirà come un altro strumento per evitare cancellazioni indesiderate.

Inoltre, qualcosa come suggerito da Derobert sarebbe il migliore; basta copiare / incollare lo script in un file / terminal-editor e adattarlo alle proprie esigenze specifiche, e i file / le directory verranno spostati in una singola directory (i cui contenuti è possibile controllare / verificare) che è possibile rimuovere semplicemente impartendo il rm -rfcomando.

Un'altra opzione è quella di utilizzare un'applicazione GUI, come il file manager, e selezionare semplicemente tutti i file / cartelle applicabili che si desidera eliminare. Controlla le pagine del manuale della tua distribuzione se non disponi delle autorizzazioni.

Infine, se le cartelle sono vuote - essenzialmente nomi di file semplici - è possibile utilizzare il rmdircomando per eliminarle. Non funziona per tutto ciò che potresti voler eliminare, ma ti tornerà utile quando vuoi fare un po 'di "pulizia della casa". ** Potresti provare l' -p --ignore-fail-on-non-emptyopzione, che ti permetterà di eliminare alcune sottodirectory così come i loro "genitori" vuoti - le directory in cui risiedono.


Questa è davvero una buona idea sulla creazione di uno script separato che posso richiedere questo comando. Puoi spiegare cosa fanno esattamente le opzioni -i e -I? Grazie!
Evster

-L'opzione ti chiederà una volta dopo aver premuto "Invio" per confermare che si desidera rimuovere questo (quando ci sono più di 3 file / cartelle "selezionati"); mentre l'opzione -i emetterà un prompt per ogni file, sul quale puoi semplicemente confermare toccando "y" e "Enter" - qualsiasi cosa oltre a una risposta affermativa comporterà il salto di quel file specifico durante il processo di rimozione.
ILMostro_7,

1

Per prima cosa devi elencare le directory e poi rimuoverle, senza ostacolare i file normali, ls -d * /, elenca solo le sottodirectory e il piping con rm rimuove le directory e i contenuti, mantenendo intatti i file sciolti.

Questo comando dovrebbe fare il lavoro,

ls -d  */ | xargs rm -rf

1
Quale sarebbe il vantaggio rispetto rm -rf -- */? printf '%s\0' */ | xargs -r0 rm -rf --aiuterebbe (nelle shell in cui printfè incorporato e no ls) a aggirare la lista arg errori troppo grandi , ma ls -d */ | xargs rm -rfnon aggiunge nulla AFAICT tranne problemi aggiuntivi.
Stéphane Chazelas,

1
@AnthonyGeoghegan, sì, ad esempio, se esistesse una directory chiamata " .."(spazio ..), rimuoverebbe il contenuto della directory padre con alcune lsimplementazioni. E non sono solo spazi, ma anche altri caratteri vuoti, newline, virgolette singole, virgolette doppie, barra rovesciata e nomi di file che iniziano con -.
Stéphane Chazelas,

2
@Ankit, potresti iniziare con mywiki.wooledge.org/ParsingLs
Stéphane Chazelas il

1
Quando comprendi appieno il suggerimento di @ StéphaneChazelas di utilizzare printfper generare un elenco in cui ogni nome è terminato dal carattere null in modo che possa essere elaborato xargscon l' -0opzione, ti consiglio di modificare la tua risposta per aggiornarla con la sua variazione. Sarei abbastanza sicuro che sarebbe felice per te di usare il suo frammento di codice se lo capisci e hai imparato come protegge da comportamenti indesiderati causati da determinati nomi di file che potrebbero potenzialmente esistere.
Anthony G - giustizia per Monica,

1
L'uso xargsha un vantaggio rispetto alla risposta accettata (funziona quando c'è un numero molto grande di file / directory nella directory corrente), quindi c'è spazio per modificarlo in una risposta utile. Personalmente, ho trovato che rispondere alle domande su Stack Exchange è stata una buona esperienza di apprendimento, in particolare quando ricevo utili feedback da altri utenti.
Anthony G - giustizia per Monica,

-1

rm -rf <directory name>. Funziona. La semplice digitazione rm <directory name>porta solo al numero di sotto domande in cui ciascuna sottodirectory deve essere rimossa manualmente. Tuttavia, rm -rfaiuta a rimuovere l'intera directory insieme alle sue sottodirectory contemporaneamente.


5
L'OP ha chiesto di conservare il contenuto della directory corrente.
Stephen Rauch,
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.