52 votes

Décompression des fichiers qui sont envoyés dans un tuyau

Puis-je faire fonctionner unzip ou tout autre programme similaire sur la sortie standard? La situation est que je télécharge un fichier zip, qui est censé être décompressé à la volée.

Problème connexe : Comment puis-je rediriger un fichier téléchargé vers la sortie standard en bash?

0 votes

Cela semblait réalisable, mais il semble que ce soit seulement possible d'extraire un fichier zip et de le transmettre à une autre commande si le zip contient un seul fichier. Je voulais extraire un fichier spécifique d'un zip multi-fichier. Au lieu de transmettre, j'ai opté pour l'enchaînement de plusieurs commandes 'unzip file.zip /chemin/fichier && dostuff /chemin/fichier && rm -rf /chemin'. Bien que cela ne réponde pas à la question initiale et implique la création de fichiers temporaires, cela a satisfait mon besoin.

0 votes

Vérifiez pigz. Nous l'utilisons dans un tuyau. andrew.tumblr.com/post/2316602611

24voto

Alors qu'un fichier zip est en fait un format de conteneur, il n'y a aucune raison pour laquelle il ne peut pas être lu à partir d'un pipe (stdin) si le fichier peut facilement tenir en mémoire. Voici un script Python qui prend un fichier zip en entrée standard et extrait le contenu dans le répertoire actuel ou dans un répertoire spécifié s'il est précisé.

import zipfile
import sys
import StringIO
data = StringIO.StringIO(sys.stdin.read())
z = zipfile.ZipFile(data)
dest = sys.argv[1] if len(sys.argv) == 2 else '.'
z.extractall(dest)

Ce script peut être minifié en une seule ligne et créé en tant qu'alias.

alias unzip-stdin="python -c \"import zipfile,sys,StringIO;zipfile.ZipFile(StringIO.StringIO(sys.stdin.read())).extractall(sys.argv[1] if len(sys.argv) == 2 else '.')\""

Il est maintenant facile de dézipper la sortie de wget.

wget http://your.domain.com/your/file.zip -O - | unzip-stdin target_dir

1 votes

Vous et Python déchirez!!!

5 votes

Joli one-liner, et +1 pour avoir mentionné que le fichier doit tenir en mémoire. (Malheureusement, il n'y a aucun moyen de dézipper un fichier pkzip en raison de la structure du format de fichier).

3 votes

Gardez à l'esprit que tout cela est mis en mémoire avant l'extraction

18voto

David Pashley Points 22851

Cela a peu de chances de fonctionner comme vous vous y attendez. Zip n'est pas seulement un format de compression, mais aussi un format de conteneur. Il regroupe les fonctions à la fois de tar et de gzip/bzip2 en un seul. Cela étant dit, si votre zip contient un seul fichier, vous pouvez utiliser unzip -p pour extraire les fichiers vers stdout. Si vous avez plus d'un fichier, il n'y a aucun moyen pour vous de dire où ils commencent et se terminent.

Quant à la lecture depuis stdin, la page man de unzip contient cette phrase :

Les archives lues à partir de l'entrée standard ne sont pas encore prises en charge, sauf avec funzip (et alors seul le premier membre de l'archive peut être extrait).

Vous pourriez avoir un peu de chance avec funzip.

0 votes

Si le zip contient plusieurs fichiers, alors -p peut imprimer un seul fichier en utilisant le nom du fichier comme paramètre : unzip -p temp.zip fichier-à-l'intérieur-du-zip

15voto

Todd Partridge Points 231

J'aime utiliser curl parce qu'il est installé par défaut (le -L est nécessaire pour les redirections qui ont souvent lieu):

curl -L http://example.com/file.zip | bsdtar -xvf - -C /chemin/vers/le/dossier/

Cependant, bsdtar n'est pas installé par défaut, et je n'ai pas réussi à faire fonctionner funzip.

0 votes

Fonctionne également très bien avec plusieurs fichiers

0 votes

J'ai voulu lister les fichiers, et les autres réponses étaient très peu utiles, la plupart rejetant le problème.

0 votes

Bsdtar est magique et prend en charge des fonctionnalités telles que --strip-components ou -s (substituer). Les utilisateurs venant de tar trouveront cet outil comme magique pour les fichiers zip.

10voto

ruario Points 191

Ceci est une reprise de ma réponse à une question similaire :

Le format de fichier ZIP comprend un répertoire (index) à la fin de l'archive. Ce répertoire indique où, à l'intérieur de l'archive, chaque fichier est situé et permet ainsi un accès rapide et aléatoire, sans lire l'ensemble de l'archive.

Cela semble poser un problème lors de la tentative de lecture d'une archive ZIP via un tube, car l'index n'est pas consulté tant que la fin et donc les membres individuels ne peuvent pas être extraits correctement tant que le fichier n'a pas été entièrement lu et n'est plus disponible. Il n'est donc pas étonnant que la plupart des décompresseurs ZIP échouent simplement lorsque l'archive est fournie via un tube.

Le répertoire à la fin de l'archive n'est pas le seul endroit où les informations méta des fichiers sont stockées dans l'archive. De plus, les entrées individuelles incluent également ces informations dans un en-tête de fichier local, à des fins de redondance.

Bien que tous les décompresseurs ZIP n'utiliseront pas les en-têtes de fichiers locaux lorsque l'index n'est pas disponible, les interfaces tar et cpio vers libarchive (alias bsdtar et bsdcpio) peuvent et vont le faire lors de la lecture via un tube, ce qui signifie que ce qui suit est possible :

wget -qO- http://exemple.org/fichier.zip | bsdtar -xvf-

8voto

nik Points 6970

Ce que vous voulez faire, c'est faire en sorte que unzip prenne un fichier ZIPpé en entrée standard au lieu de comme argument. C'est généralement facilement pris en charge par des outils du type gzip et tar avec un argument -. Mais le standard unzip ne le fait pas (bien que, il prenne en charge l'extraction vers un tube). Cependant, tout n'est pas perdu...

Regardez la page manuel de funzip.

funzip sans argument de fichier agit comme un filtre ; c'est-à-dire, il suppose qu'une archive ZIP (ou un fichier gzip) est transmise à l'entrée standard, et extrait le premier membre de l'archive vers la sortie standard. Lorsque stdin provient d'un périphérique tty, funzip suppose que cela ne peut pas être un flux de données compressées (binaires) et affiche plutôt un texte d'aide court. S'il y a un argument de fichier, alors l'entrée est lue à partir du fichier spécifié au lieu de stdin.

Étant donné la limitation de l'extraction d'un seul membre, funzip est le plus utile en conjonction avec un programme d'archivage secondaire tel que tar(1). La section suivante inclut un exemple illustrant cette utilisation dans le cas de sauvegardes sur disque vers une bande.

Cela va bien avec l'idée que la plupart des archives Linux sont généralement TARées puis ZIPpées de quelque manière (gzip, bzip, entre autres). Cela fonctionnera pour vous si vous avez un tar.ZIP.


Il convient de noter que funzip est écrit par l'auteur original d'Info-ZIP, Mark Adler. Il écrit dans la page manuel de funzip,

cette fonctionnalité devrait être incorporée dans unzip lui-même (future version).

cependant, aucune mise à jour de ce type n'est observée. Je soupçonne que Mark l'a jugé inutile puisque d'autres méthodes d'archivage fonctionnaient facilement avec TAR.

0 votes

Juste un commentaire; certaines personnes aimeraient que Python ou n'importe quel langage soit une option pour décompresser. Un exemple parfait est Heroku qui n'inclut ni tar ni unzip dans son système. Une solution de contournement consiste à utiliser jar en installant Java, ce qui est autorisé.

0 votes

Il y a plus d'informations sur la gestion des limitations de funzip et des outils similaires (en particulier sur le fait qu'ils sont uniquement capables d'afficher le premier membre d'une archive) dans cette réponse : unix.stackexchange.com/a/211286/77539

0 votes

À savoir, funzip ne peut extraire que le premier fichier membre d'une archive ZIP.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X