2010-04-25 5 views
6

Ho visto i loop per decomprimere tutti i file zip in una directory. Tuttavia, prima che corro questo, avrei preferito assicurarsi che ciò che sto per eseguire lavorerà a destra:Un ciclo di shell può decomprimere tutti i file in una directory?

for i in dir; do cd $i; unzip '*.zip'; rm -rf *.zip; cd ..; done 

Fondamentalmente io voglio che guardare l'output di "dir" vedi tutte le cartelle, per ogni directory cd in esso, decomprimere tutti gli archivi zip, quindi rimuoverli, quindi tornare indietro e farlo di nuovo fino a quando non ci sono più.

È qualcosa che dovrei fare in un singolo comando o dovrei considerare di farlo in Perl?

+1

Ciao e benvenuto su StackOverflow. Per rendere il tuo codice più leggibile, usa il codice –

+1

per le tue informazioni, puoi usare cd - per tornare nella directory precedente. – Aif

+0

@Patrick done :) – DVK

risposta

1

parzialmente testato:

find . -type d -exec sh -c "cd \"{}\" ; unzip \"*.zip\" ; rm \"*.zip\" " \; 

esegue catena cd/unzip/rm per ogni sottodirectory.

+0

Finora questo funziona, dove l'altra risposta non può prendere cose come "Nome cartella con uno spazio", tuttavia non rimuove gli archivi .zip. – helpwithshell

+0

Penso che devi usare 'find ... | xargs -0 ... 'per gestire gli spazi bianchi, o le virgolette sfuggite fanno il lavoro? – Anycorn

+0

Alla fine sono stato in grado di modificare la riga di comando su: find. -name "* .zip" -exec sh -c "rm -rf \" {} \ "" \; per rimuovere tutti gli archivi .zip rimasti. grazie – helpwithshell

1

Usa * per ottenere il contenuto della directory corrente:

for i in *; do cd "$i"; ...etc... ; done 

Si dovrebbe anche fare in modo che qualcosa è una directory prima di tentare di cd in esso. In bash questo è fatto come segue:

if [ -d "$i" ]; then ...etc... ; fi 

si dovrebbe anche essere attenti a controllare che l'operazione è riuscita decomprimere prima di eliminare il file zip. Non è necessario utilizzare l'eliminazione forza ricorsiva per rimuovere un singolo file.

Penso che questo stia spingendo al limite per ciò che è sensato fare una sola riga. Inseriscilo in uno script di shell e formattalo su più righe.

2

si dovrebbe andare bene in generale. Per il debug il solo prefisso di tutti i comandi nel ciclo con echo ti dirà come si espandono le variabili. È anche possibile utilizzare sempre rm -i da richiedere invece di fare rm andare avanti con qualsiasi cosa con -f.

Le virgolette singole nella chiamata unzip decomprimeranno solo i file denominati *.zip, ad esempio lo * non si espanderà. Usa invece le virgolette doppie (o nessuna virgolette).

Il loop ora presuppone che tutte le directory $i siano direttamente sotto quella corrente. Una soluzione più generale sarebbe utilizzare lo stack di directory (pushd e popd);

for i in $dir; do 
    pushd $i 
    unzip *.zip 
    rm -rf *.zip 
    popd 
done 
+0

ho dovuto cambiare il primo da per i in dir a per i in *, è roba non compressa, tuttavia ha avuto problemi con i file che contenevano spazi nel nome. – helpwithshell

+0

@help: ho assunto implicitamente che 'dir' era una variabile quando non era così il mio esempio era sbagliato. Fixato qui e ora si presuppone che 'dir' sia una variabile che contiene l'elenco delle directory. –

2

Alcuni punti aggiungendo a ciò che altri hanno detto:

  • Se si mette un parametro tra virgolette singole, come in '*.zip', la shell non farà espansione delle wild card e decomprimere cercherà di elaborare un archivio che è letteralmente chiamato *.zip
  • Non utilizzare -r come parametro su rm se si desidera rimuovere singoli file. Questo è inutilmente pericoloso dato che l'eliminazione ricorsiva di sottodirectory probabilmente non dovrebbe essere intesa.
  • Si dovrebbe controllare il codice di ritorno di unzip e rimuovere solo il file zip se la decompressione ha avuto successo (per esempio si potrebbe dire if unzip *.zip; then rm *.zip; fi, o anche utilizzare un esplicito for ciclo per elaborare i file zip uno per uno)
0

Quando si desidera sapere se un qualcosa funziona, ma sono prudenti del suo conseguenze distruttive, fare un po 'alla volta:

Assicurati di ottenere i file corretti:

for i in dir; do cd $i; echo $i; cd ..; done 

Assicurarsi la possibilità di decomprimere i file prima di eliminare i file:

for i in dir; do cd $i; unzip '*.zip'; cd ..; done 

E, prima di fare il pieno monty, fare un back-up della directory.