Question Décompression des fichiers qui arrivent par un tuyau


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

Question connexe: Comment puis-je diriger un fichier téléchargé vers une sortie standard dans bash?


36
2018-06-16 12:32


origine


Cela semblait être faisable, mais il semble qu'il ne soit possible d'extraire un fichier zip et de diriger le fichier vers une autre commande que si le fichier zip ne contient qu'un seul fichier. Je voulais extraire un fichier spécifique d'un zip multi-fichier. Au lieu de la tuyauterie, j’ai décidé d’enchaîner plusieurs commandes 'décompressez fichier.zip / chemin / fichier && dostuff / chemin / fichier && rm-rf / chemin'. En ne répondant pas à la question initiale et en créant des fichiers temporaires, il a avoir besoin. - Stan Kurdziel
Découvrez Pigz. Nous l'utilisons dans un tuyau. andrew.tumblr.com/post/2316602611 - dmourati


Réponses:


Bien qu'un fichier zip soit en fait un format conteneur, il n'y a aucune raison pour qu'il ne puisse pas être lu à partir d'un tube (stdin) si le fichier peut tenir dans la mémoire assez facilement. Voici un script Python qui prend un fichier zip en entrée standard et en extrait le contenu dans le répertoire actuel ou dans un répertoire spécifié, le cas échéant.

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 réduit à une ligne et créé comme un 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 '.')\""

Maintenant décompressez facilement la sortie de wget.

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

21
2018-06-15 19:44



Toi et Python Rock !!! - Farid Nouri Neshat
Nice one-liner, et +1 pour mentionner que le fichier doit tenir dans la mémoire. (Il n’existe malheureusement aucun moyen de décompresser un fichier pkzip en raison de la structure de format de fichier). - lxgr
Gardez à l'esprit que tout le tampon en mémoire avant d'extraire - William Casarin
il n'y a aucune raison pour laquelle il ne peut pas être lu comme un flux si le fichier peut entrer dans la mémoire assez facilement n'est pas vraiment précis. La raison pour laquelle vous êtes obligé de mettre en mémoire tampon la totalité de l'archive zip avant d'extraire le contenu est spécifiquement due au fait qu'elle ne peut pas être lue sous forme de flux. Bien sûr, il peut toujours être utile d’éviter d’écrire l’archive zip dans un fichier. - Håkan Lindqvist
C'est ne pas un flux, vous lisez le fichier entier en mémoire en utilisant le .read() méthode - Romuald Brunet


Il est peu probable que cela fonctionne comme vous le souhaitez. Le zip n'est pas simplement un format de compression, mais aussi un format de conteneur. Il regroupe les travaux de tar et gzip.bzip2. Cela dit, si votre zip ne contient qu'un seul fichier, vous pouvez utiliser unzip -p pour extraire les fichiers sur stdout. Si vous avez plus d'un fichier, vous n'avez aucun moyen de dire où ils commencent et s'arrêtent.

En ce qui concerne stdin, la page de manuel unzip contient la phrase suivante:

Les archives lues à partir d'une entrée standard ne sont pas encore supportées, à l'exception de funzip (seul le premier membre de l'archive peut être extrait).

Vous pourriez avoir un peu de chance avec funzip.


17
2018-06-16 12:45



Si zip contient plusieurs fichiers, -p peut imprimer un fichier unique en utilisant le nom de fichier comme paramètre: unzip -p temp.zip file-inside-zip - Taavi Ilves


Ce que vous voulez faire, c'est unzip prenez un fichier ZIPped sur son entrée standard plutôt que sous forme d'argument. Ceci est généralement facilement supporté par gzip et tar genre d'outils avec un - argument. Mais la norme unzip ne fait pas cela (cependant, il supporte l'extraction vers un tuyau). Cependant, tout n'est pas perdu...

Regarder funzip page de manuel.

funzip sans argument de fichier agit comme un filtre; c’est-à-dire qu’il suppose qu’une archive ZIP (ou un fichier gzip'd) est en cours de traitement dans la norme          input et extrait le premier membre de l’archive sur stdout.          Lorsque stdin provient d’un appareil tty, funzip suppose que cela ne peut pas être          un flux de données compressées (binaires) et affiche un court texte d'aide,          au lieu. S'il y a un argument de fichier, l'entrée est lue à partir du          fichier spécifié au lieu de stdin.

Funzip est le plus utile compte tenu de la limitation de l'extraction d'un seul membre          en conjonction avec un programme d'archivage secondaire tel que tar (1). le          la section suivante comprend un exemple illustrant cet usage dans le          cas de sauvegardes de disque sur bande.

Cela va bien avec l'idée que la plupart des archives Linux sont habituellement TAR'ed et ensuite ZIPped d'une manière ou d'une autre (gzip, bzip, et autres). Cela fonctionnera pour vous si vous avez un tar.ZIP.


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

this functionality should be incorporated into unzip itself (future release).

Cependant, aucune mise à jour de ce type n'est visible. Je soupçonne que Mark l’a trouvé inutile étant donné que d’autres méthodes d’archivage fonctionnent facilement avec TAR.


7
2018-06-16 12:46



Juste un commentaire; Certaines personnes aimeraient utiliser python ou n’importe quel langage pour décompresser. Heroku en est un bon exemple. Il ne comprend ni tar ni unzip sur son système. Une solution consiste à utiliser jar en installant Java qui est autorisé. - Nick
Il y a plus à propos de la gestion des limitations de funzip et d'outils similaires (en particulier d'être capable de montrer le premier membre d'une archive) dans cette réponse: unix.stackexchange.com/a/211286/77539 - Joshua Goldberg


J'aime utiliser curl car il est installé par défaut (le -L est nécessaire pour les redirections qui se produisent souvent):

curl -L http://example.com/file.zip | bsdtar -xvf - -C /path/to/directory/

cependant, bsdtar n'est pas installé par défaut, et je ne pouvais pas obtenir funzip travailler.


6
2018-03-05 15:47



Fonctionne également très bien avec plusieurs fichiers - jonnor


Ce n'est pas possible avec Info-Zip, qui est l'implémentation OSS la plus courante. Plus important encore, ce n'est pas recommandé en raison de la structure des archives ZIP.

Si un changement de format est viable pour vous, envisagez plutôt d'utiliser tar (1). Il est assez content des entrées / sorties en streaming et, en fait, l'attend par défaut.

De plus, vous pouvez souvent savoir si les applications attendent des entrées / sorties en streaming en spécifiant "-" pour un nom de fichier. Comme vous pouvez l'imaginer, Info-Zip ne considère pas cela comme un argument valable.


4
2018-06-16 12:53





En zsh, vous pouvez effectuer les opérations suivantes:

unzip =( curl http://example.com/someZipFile.zip )

4
2017-11-14 22:09





Ceci est un repost 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ù, dans l’archive, se trouve chaque fichier et permet ainsi un accès rapide et aléatoire, sans lire toute l’archive.

Cela semblerait poser un problème lors de la tentative de lecture d'une archive ZIP par un canal, dans la mesure où l'index n'est accessible qu'à la toute fin et que les membres individuels ne peuvent pas être correctement extraits avant la lecture complète du fichier et sa non disponibilité. . En tant que tel, il ne semble pas surprenant que la plupart des décompresseurs ZIP échouent simplement lorsque l'archive est fournie via un tuyau.

Le répertoire à la fin de l'archive n'est pas le seulement emplacement où les méta-informations du fichier sont stockées dans les archives. 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'utilisent pas les en-têtes de fichiers locaux lorsque l'index n'est pas disponible, les versions de tar et cpio se terminent par libarchive (a.k.a. bsdtar et bsdcpio) peut et va faites-le en lisant à travers un tuyau, ce qui signifie que ce qui suit est possible:

wget -qO- http://example.org/file.zip | bsdtar -xvf-

4
2018-04-16 17:54





En fait, j'avais besoin de quelque chose d'un peu plus complexe - extraire un fichier spécifique s'il existe. La difficulté étant que le flux de fichier d'entrée ne soit peut-être pas un fichier zip, et dans ce cas, j'avais besoin de continuer dans le tuyau. Voici ma solution (principalement grâce à la solution Jason R. Coombs)

python -c "import zipfile,sys,StringIO
data=sys.stdin.read()
try:
    z=zipfile.ZipFile(StringIO.StringIO(data))
    z.open(\"$1\")
    sys.stdout.write(z.read(\"$1\"))
except (RuntimeError, zipfile.BadZipfile):
    sys.stdout.write(data)"

J'ai sauvegardé ceci en tant que fichier nommé "effpoptp" (pas un nom simple) dans le dossier "/ bin" sur ma machine, donc le tester ressemble à ça:

cat defaultModel.mwb|effpoptp "document.mwb.xml"

Le but est de contrôler la version des fichiers MySQL Workbench, le fichier pouvant être le fichier xml nommé comme fichier de workbench ou le fichier complet de workbench.


1
2017-11-13 18:01





L’utilitaire commun le plus simple disponible pour ce faire est jar, ce qui présume que STDIN est utilisé si vous ne lui passez aucun argument de fichier. Il faut aussi des arguments similaires à ceux du tar programme d'opérations.

par exemple. lister le contenu d'une archive

curl https://my.example.com/file.zip | jar t

Bien que Java ne soit pas toujours installé, sur les machines où il se trouve, jar est certainement la méthode la plus pratique pour ce faire.


1
2018-06-04 12:15





Republication de ma réponse:

BusyBox's unzip peut prendre stdin et extraire tous les fichiers.

wget -qO- http://downloads.wordpress.org/plugin/akismet.2.5.3.zip | busybox unzip -

Le tiret après unzip est d'utiliser stdin comme entrée.

Vous pouvez même,

cat file.zip | busybox unzip -

Mais c'est juste redondant de unzip file.zip.

Si votre distribution utilise BusyBox par défaut (par exemple, Alpine), exécutez simplement unzip -.


0
2017-10-11 12:13