Décompression de plusieurs fichiers à la fois

27

J'ai plus de 200 .zipfichiers dans un dossier. Je ne veux pas les décompresser un par un. Je veux extraire ceux qui utilisent une seule commande ou un seul script. Comment faire ça.

g_p
la source

Réponses:

38

Si vous voulez vraiment les décompresser en parallèle, vous pouvez le faire

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

Cependant, cela lancera N processus pour N fichiers .zip et pourrait être très lourd sur votre système. Pour une approche plus contrôlée, ne lançant que 10 processus parallèles à la fois, essayez ceci:

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

Pour contrôler le nombre de processus parallèles lancés, -Ppassez à ce que vous voulez. Si vous ne voulez pas recurse dans les sous-répertoires, faites-le à la place:

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

Alternativement, vous pouvez installer GNU parallel comme suggéré par @OleTange dans les commentaires et exécuter

parallel unzip ::: *zip
terdon
la source
3
L'exécution en parallèle est une bonne idée, mais les E / S disque ne seront-elles pas le principal goulot d'étranglement?
Paddy Landau
1
@PaddyLandau pas sûr, je devrais vérifier. Cela dépendra de la vitesse de l'algorithme de décompression par rapport à la vitesse du disque que j'imagine.
terdon
Utilisez -execou -execdirau lieu de la tuyauterie pour xargs. Non seulement il est plus simple à comprendre, mais il est également moins sujet aux erreurs et utilise moins de ressources système. find . -name '*.zip' -exec unzip {} ';'(Vous devez citer le point-virgule.)
Paddy Landau
@PaddyLandau la seule raison pour laquelle je lance des xargs est d'exécuter les choses en parallèle comme l'OP l'a demandé. -exec \;(vous pouvez échapper au point-virgule, pas besoin de guillemets), exécutera chaque commande séquentiellement. -exec +c'est mieux mais ça ne marchera pas ici car ce n'est pas comme ça que ça unzipmarche.
terdon
Je pense que nous avons compris le PO différemment. Vous le lisez comme le voulant en parallèle, alors que je l'ai compris comme signifiant une seule commande au lieu de plusieurs commandes. Eh bien, il a les deux méthodes maintenant :)
Paddy Landau
17

La commande parallèle GNU est bien adaptée à ce type de chose. Après:

$ sudo apt-get install parallel

ensuite

ls *.zip | parallel unzip

Cela utilisera autant de cœurs que vous en avez, en gardant chaque cœur occupé avec une décompression, jusqu'à ce qu'ils soient tous terminés.

Wayne Conrad
la source
C'est une meilleure idée d'utiliser à la echo *.zipplace pour empêcher un alias ls possible de se faufiler dans des informations supplémentaires. Cependant, cela a le même problème que la réponse de @ Guru, il casse les noms de fichiers contenant des espaces.
nyuszika7h
1
@ nyuszika7h Contrairement à xargsGNU Parallel ne se casse pas sur les noms de fichiers contenant espace / tabulation / citation. Ce n'est que si les noms de fichiers contiennent des sauts de ligne que vous devrez faire très attention. Par exemple en utilisant:parallel unzip ::: *.zip
Ole Tange
@ nyuszika7h - Ce sont de bonnes raisons pour éviter à la fois de créer des alias de commandes standard et de mettre des espaces dans les noms de fichiers.
Wayne Conrad
@ nyuszika7h en utilisant echoest aussi mauvais qu'en utilisant ls. Globbing et une boucle while sont les plus sûrs.
terdon
1
@NateEldredge Alors que cette chance était plus grande à l'époque où les systèmes n'avaient qu'un seul disque magnétique, de nos jours avec des RAID à plusieurs broches et un disque flash, cette chance est plus petite. La meilleure chose à faire est bien sûr de mesurer et de voir comment se comporte votre système. J'ai récemment utilisé un RAID à 40 broches où le parallélisme optimal pour les processus gourmands en E / S était de 10: il n'a pas accéléré 10 fois - seulement 6x, mais moins de 10 processus ont donné moins de 6x.
Ole Tange
12

Vous pouvez utiliser la commande suivante:

Changez d'abord le répertoire du terminal en un répertoire contenant des fichiers .zip:

cd /path

Exécutez ensuite cette commande pour décompresser tous les fichiers .zip:

for z in *.zip; do unzip "$z"; done
nux
la source
10

Si vous avez de nombreux .zipfichiers dans votre dossier et que vous souhaitez tous les décompresser, ouvrez le terminal et accédez à votre dossier en utilisant:

cd <path_to_folder>

Utilisez maintenant cette commande pour décompresser tout votre .zipfichier:

ls *.zip | xargs -n1 unzip
g_p
la source
3
Cela échouera si l'un des noms de fichier contient des espaces.
terdon
1
Oui vous avez raison.
g_p
Il est préférable d'utiliser à la echo *.zipplace pour empêcher un lsalias possible de se faufiler dans des informations supplémentaires, mais cela ne résout toujours pas le problème des espaces blancs.
nyuszika7h
1
@OleTange Au cas où vous ne l'auriez pas remarqué, j'ai dit qu'il échouait toujours sur les noms de fichiers avec des espaces en eux.
nyuszika7h
1
Ne dépendez jamais de la sortie de lspour les scripts, car sa sortie n'est pas bien définie entre les versions. Regardez plutôt la réponse de @terdon car elle résout tous les problèmes de cette solution.
Paddy Landau
6

Vous pouvez utiliser find avec -execcomme ça,

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

Cela va fonctionner si le fichier a un espace dans le nom.

Elliott Frisch
la source
3

Une méthode non terminale.

Sélectionnez simplement les fichiers zip, faites un clic droit sur l'un et choisissez extract here. Vous pouvez sélectionner tout ou seulement un certain nombre de fichiers zip à la fois.

Parto
la source
1

unzip \*.zip ou unzip '*.zip'

L'évident unzip *.zipne fonctionne pas, car le shell le développe unzip foo.zip bar.zip ...et unzipinterprète le premier nom de fichier comme le fichier zip et les noms de fichiers suivants comme des fichiers à extraire de ce fichier zip.

Cependant, unzipest un peu inhabituel parmi les commandes Unix en ce qu'il fait ses propres extensions glob. Si le *n'est pas développé par le shell, décompressez le fera et interprétera tous les noms de fichiers résultants en tant que fichiers zip à traiter. Donc, dans ce cas particulier, on peut s'en tirer sans forboucle ou xargssimilaire.

Nate Eldredge
la source