Decomprimere più file contemporaneamente


27

Ho più di 200 .zipfile in una cartella. Non voglio decomprimerli uno per uno. Voglio estrarre quelli usando un singolo comando o script. Come farlo.

Risposte:


38

Se vuoi davvero decomprimerli in parallelo, potresti farlo

for i in *zip; do unzip "$i" & done

Ciò, tuttavia, avvierà N processi per file N .zip e potrebbe essere molto pesante per il tuo sistema. Per un approccio più controllato, lanciando solo 10 processi paralleli alla volta, prova questo:

find . -name '*.zip' -print0 | xargs -0 -I {} -P 10 unzip {}

Per controllare il numero di processi paralleli avviati, -Ppassa a quello che desideri. Se non si desidera ricorrere in sottodirectory, fare invece questo:

find . -maxdepth 1 -name '*.zip' -print0 | xargs -0 -I {} -P 10 unzip {}

In alternativa, è possibile installare GNU parallelo come suggerito da @OleTange nei commenti ed eseguire

parallel unzip ::: *zip

3
L'esecuzione in parallelo è una buona idea, ma l'I / O su disco non sarà il principale collo di bottiglia?
Paddy Landau,

1
@PaddyLandau non sono sicuro, dovrei controllare. Dipenderà dalla velocità dell'algoritmo di decompressione rispetto alla velocità del disco che immagino.
terdon,

Utilizzare -execo -execdiranziché eseguire il piping a xargs. Non solo è più semplice da capire, ma è anche meno soggetto a errori e utilizza meno risorse di sistema. find . -name '*.zip' -exec unzip {} ';'(Devi citare il punto e virgola.)
Paddy Landau,

@PaddyLandau l'unica ragione per cui sto eseguendo il piping su xargs è far funzionare le cose in parallelo come richiesto dall'OP. -exec \;(puoi sfuggire al punto e virgola, senza bisogno di virgolette), eseguirà ogni comando in sequenza. -exec +è meglio ma non funzionerà qui poiché non è così che unzipfunziona.
terdon,

Penso che abbiamo compreso l'OP in modo diverso. Lo leggi come volerlo in parallelo, mentre io l'ho capito come significato di un singolo comando anziché di più comandi. Bene, ora ha entrambi i metodi :)
Paddy Landau,

17

Il comando parallelo GNU si adatta perfettamente a questo tipo di cose. Dopo:

$ sudo apt-get install parallel

Poi

ls *.zip | parallel unzip

Questo utilizzerà tutti i core che hai, mantenendo ogni core occupato con una decompressione, fino a quando non sono stati completati.


È un'idea migliore da usare echo *.zipinvece per impedire a un possibile alias di intrufolarsi in ulteriori informazioni. Tuttavia, questo ha lo stesso problema della risposta di @ Guru, si interrompe sui nomi dei file contenenti spazi bianchi.
nyuszika7h

1
@ nyuszika7h Contrariamente a xargsGNU Parallel non si interrompe sui nomi dei file contenenti spazio / tab / quote. Solo se i nomi dei file contengono newline dovrai prestare particolare attenzione. Ad esempio utilizzando:parallel unzip ::: *.zip
Ole Tange

@ nyuszika7h - Questi sono buoni motivi per evitare sia l' aliasing dei comandi standard, sia l' inserimento di spazi nei nomi dei file.
Wayne Conrad,

@ nyuszika7h usare echoè male come usare ls. Globbing e un ciclo while è il più sicuro.
terdon,

1
@NateEldredge Mentre quella possibilità era più grande nel tempo in cui i sistemi avevano un solo disco magnetico, oggigiorno con RAID con più mandrini e disco flash tale possibilità è minore. La cosa migliore da fare è ovviamente misurare e vedere come si comporta il tuo sistema. Recentemente ho usato un RAID a 40 mandrini in cui il parallelismo ottimale per i processi affamati di I / O era 10: non ha dato una velocità 10x - solo un 6x, ma meno di 10 processi ha dato meno di 6x.
Ole Tange

12

Puoi usare il seguente comando:

Prima cambia directory nel terminale in directory che contiene file .zip:

cd /path

Quindi eseguire questo comando per decomprimere tutti i file .zip:

for z in *.zip; do unzip "$z"; done

10

Se hai molti .zipfile nella tua cartella e vuoi decomprimerli tutti, apri il terminale e vai alla tua cartella usando:

cd <path_to_folder>

Ora usa questo comando per decomprimere tutto il tuo .zipfile:

ls *.zip | xargs -n1 unzip

3
Ciò fallirà se uno dei nomi dei file contiene spazi bianchi.
terdon,

1
sì hai ragione.
g_p,

È un'idea migliore da utilizzare echo *.zipinvece per impedire a un possibile lsalias di intrufolarsi in ulteriori informazioni, tuttavia ciò non risolve ancora il problema degli spazi bianchi.
nyuszika7h

1
@OleTange Nel caso in cui non se ne accorga, ho detto che non riesce ancora sui nomi dei file con spazi bianchi.
nyuszika7h

1
Non dipendere mai dall'output di lsfor script, poiché l'output non è ben definito tra le versioni. Guarda invece la risposta di @terdon in quanto risolve tutti i problemi di questa soluzione.
Paddy Landau,

6

Puoi usare find con in questo -execmodo,

find . -name "*.zip" -exec unzip {} \;

Questo sarà funziona se il file ha uno spazio nel nome.


3

Un metodo non terminale.

Basta selezionare i file zip, fare clic destro su uno e scegliere extract here. Puoi selezionare tutti o solo alcuni file zip alla volta.


1

unzip \*.zip o unzip '*.zip'

L'ovvio unzip *.zipnon funziona, perché la shell lo espande unzip foo.zip bar.zip ...e unzipinterpreta il primo nome file come file zip e i seguenti nomi file come file da estrarre da quel file zip.

Tuttavia, unzipè un po 'insolito tra i comandi Unix in quanto esegue le proprie espansioni glob. Se il *non è espanso dalla shell, decomprimerlo lo farà e interpreterà tutti i nomi di file risultanti come file zip da elaborare. Quindi, in questo caso speciale, si può scappare senza un forciclo o xargssimili.

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.