Frage Dateien entpacken, die durch eine Pipe fliegen


Kann ich entpacken oder ähnliche Programme mit der Standardausgabe arbeiten? Die Situation ist, ich lade eine Zip-Datei, die im laufenden Betrieb entpackt werden soll.

Verwandtes Problem: Wie übertrage ich eine heruntergeladene Datei zur Standardausgabe in bash?


36
2018-06-16 12:32


Ursprung


Dies scheint so zu sein, als wäre es machbar, aber es sieht so aus, als wäre es nur möglich, eine Zip-Datei zu extrahieren und die Datei an einen anderen Befehl weiterzuleiten, wenn die Zip-Datei nur eine einzige Datei enthält. Ich wollte eine bestimmte Datei aus einem Multi-Datei-Zip extrahieren. Anstatt zu pumpen, habe ich mehrere Kommandos 'entpackt zip.zip / pfad / datei & & dostuff / pfad / datei && rm -rf / pfad' umgestellt. Obwohl die ursprüngliche Frage nicht beantwortet wurde und temporäre Dateien erstellt wurden, hat es meine zufrieden gestellt brauchen. - Stan Kurdziel
Schau dir Schwein an. Wir benutzen es in einer Pfeife. andrew.tumblr.com/post/2316602611 - dmourati


Antworten:


Während eine Zip-Datei tatsächlich ein Container-Format ist, gibt es keinen Grund, warum sie nicht aus einer Pipe (Stdin) gelesen werden kann, wenn die Datei leicht genug in den Speicher passt. Hier ist ein Python-Skript, das eine Zip-Datei als Standardeingabe verwendet und den Inhalt in das aktuelle Verzeichnis oder in ein angegebenes Verzeichnis extrahiert, falls angegeben.

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)

Dieses Skript kann auf eine Zeile verkleinert und als Alias ​​erstellt werden.

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 '.')\""

Jetzt entpacken Sie einfach die Ausgabe von wget.

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

21
2018-06-15 19:44



Du und Python Rock !!! - Farid Nouri Neshat
Nice one-liner und +1 für die Erwähnung, dass die Datei in den Speicher passen muss. (Es gibt leider keine Möglichkeit, eine pkzip-Datei aufgrund der Struktur des Dateiformats zu entpacken). - lxgr
Beachten Sie, dass dies alles im Speicher zwischenspeichert, bevor es extrahiert wird - William Casarin
Es gibt keinen Grund, warum es nicht als Stream gelesen werden kann, wenn die Datei leicht genug in den Speicher passt ist nicht wirklich genau. Der Grund, warum Sie gezwungen sind, das gesamte zip-Archiv im Speicher zu puffern, bevor Sie den Inhalt extrahieren, liegt insbesondere daran, dass es nicht als Stream gelesen werden kann. Natürlich kann es immer noch sinnvoll sein, das Zip-Archiv nicht in eine Datei zu schreiben. - Håkan Lindqvist
Das ist nicht Ein Stream, Sie lesen die gesamte Datei im Speicher mit dem .read() Methode - Romuald Brunet


Dies wird wahrscheinlich nicht funktionieren, wie Sie es erwarten. Zip ist nicht nur ein Komprimierungsformat, sondern auch ein Containerformat. Es rollt die Jobs von tar und gzip.bzip2 in eins zusammen. Wenn Ihre ZIP-Datei jedoch eine einzige Datei enthält, können Sie sie mit entpacken -p extrahieren. Wenn Sie mehr als eine Datei haben, können Sie nicht sagen, wo sie starten und stoppen.

Wie beim Lesen von stdin, hat die Entpacker-Man-Seite folgenden Satz:

Von der Standardeingabe gelesene Archive werden noch nicht unterstützt, außer mit Funzip (und dann kann nur das erste Mitglied des Archivs extrahiert werden).

Vielleicht haben Sie Glück mit Funzip.


17
2018-06-16 12:45



Wenn zip mehrere Dateien enthält, kann -p eine einzelne Datei mit dem Dateinamen als Parameter ausgeben: unzip -p temp.zip file-inside-zip - Taavi Ilves


Was Sie tun möchten, ist, machen unzip Nehmen Sie eine ZIP-Datei auf der Standardeingabe und nicht als Argument. Dies wird normalerweise leicht von unterstützt gzip und tar Art von Werkzeugen mit a - Streit. Aber der Standard unzip tut das nicht (obwohl es die Extraktion zu einer Pipe unterstützt). Aber alles ist nicht verloren ...

Ansehen Funzip Handbuchseite.

funzip ohne Dateiargument agiert als Filter; Das heißt, es wird davon ausgegangen, dass ein ZIP-Archiv (oder eine Gzip-Datei) in den Standard geleitet wird          Eingabe, und es extrahiert das erste Mitglied aus dem Archiv nach stdout.          Wenn stdin von einem tty-Gerät kommt, geht funzip davon aus, dass dies nicht sein kann          ein Strom von (binären) komprimierten Daten und zeigt einen kurzen Hilfetext,          stattdessen. Wenn ein Dateiargument vorhanden ist, wird die Eingabe von der Datei gelesen          angegebene Datei anstelle von stdin.

Angesichts der Einschränkung bei der Extraktion von Einzelelementen ist funzip am nützlichsten          in Verbindung mit einem sekundären Archivierungsprogramm wie tar (1). Das          Der folgende Abschnitt enthält ein Beispiel zur Veranschaulichung dieser Verwendung in der          Bei Disk-Backups auf Band.

Dies passt gut zu der Idee, dass die meisten Linux-Archive normalerweise mit TARs versehen und dann in irgendeiner Weise gezippt werden (gzip, bzip, et al). Dies wird für Sie funktionieren, wenn Sie eine haben tar.ZIP.


Es ist erwähnenswert, dass funzip geschrieben von Info-ZIP Originalautor Mark Adler. Er schreibt in die Funzip Manpage,

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

Es wird jedoch keine solche Aktualisierung angezeigt. Ich vermute, dass Mark es unnötig fand, da andere Archivierungsmethoden problemlos mit TAR funktionierten.


7
2018-06-16 12:46



Nur ein Kommentar; Manche Leute möchten Python oder eine andere Sprache als eine Option zum Entpacken. Ein gutes Beispiel ist Heroku, das kein tar oder unzip auf seinem System enthält. Ein Problem besteht darin, jar zu verwenden, indem Java installiert wird, was erlaubt ist. - Nick
In dieser Antwort geht es mehr um Einschränkungen von funzip und ähnlichen Werkzeugen (insbesondere nur um das erste Mitglied eines Archivs anzuzeigen): unix.stackexchange.com/a/211286/77539 - Joshua Goldberg


Ich benutze gerne curl, weil es standardmäßig installiert ist (die -L wird für häufig auftretende Weiterleitungen benötigt):

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

Jedoch, bsdtar ist standardmäßig nicht installiert, und ich konnte nicht bekommen funzip arbeiten.


6
2018-03-05 15:47



Funktioniert auch mit mehreren Dateien - jonnor


Es ist nicht möglich mit Info-Zip, der am häufigsten verwendeten OSS-Implementierung. Noch wichtiger ist jedoch, dass es aufgrund der Konstrukte von ZIP-Archiven nicht empfohlen wird.

Wenn ein Formatwechsel für Sie sinnvoll ist, sollten Sie stattdessen tar (1) verwenden. Es ist ziemlich glücklich mit Streaming-Input / Output und erwartet es tatsächlich standardmäßig.

Außerdem können Sie oft feststellen, ob Anwendungen Streaming-Eingabe / Ausgabe erwarten, indem Sie für einen Dateinamen "-" angeben. Info-Zip, wie Sie sich vorstellen können, behandelt dies nicht als ein gültiges Argument.


4
2018-06-16 12:53





In zsh können Sie Folgendes tun:

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

4
2017-11-14 22:09





Dies ist ein Umtausch von meine Antwort zu einer ähnlichen Frage:

Das ZIP-Dateiformat enthält ein Verzeichnis (Index) am Ende des Archivs. In diesem Verzeichnis wird angegeben, wo sich innerhalb des Archivs jede Datei befindet und somit ein schneller, wahlfreier Zugriff ermöglicht wird, ohne das gesamte Archiv zu lesen.

Dies scheint ein Problem zu sein, wenn versucht wird, ein ZIP-Archiv durch eine Pipe zu lesen, da auf den Index bis zum Ende nicht zugegriffen wird und einzelne Mitglieder nicht korrekt extrahiert werden können, bis die Datei vollständig gelesen wurde und nicht mehr verfügbar ist . Daher überrascht es nicht, dass die meisten ZIP-Dekomprimierer einfach versagen, wenn das Archiv über eine Pipe versorgt wird.

Das Verzeichnis am Ende des Archivs ist nicht das nur Speicherort, an dem Datei-Meta-Informationen im Archiv gespeichert werden. Zusätzlich enthalten einzelne Einträge diese Information in einem lokalen Dateikopf für Redundanzzwecke.

Obwohl nicht jeder ZIP-Dekompressor lokale Dateikopfzeilen verwendet, wenn der Index nicht verfügbar ist, enden die tar- und cpio-Front in libarchive (a.k.a. bsdtar und bsdcpio) kann und will tun Sie dies, wenn Sie durch eine Pipe lesen, was bedeutet, dass Folgendes möglich ist:

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

4
2018-04-16 17:54





Ich brauchte etwas komplexeres - extrahiere eine bestimmte Datei, wenn sie existiert. Die Schwierigkeit dabei ist, dass der Eingabedatei-Stream keine Zip-Datei ist, und in diesem Fall brauchte ich ihn, um durch die Pipe fortzuschreiten. Hier ist meine Lösung (Danke hauptsächlich an Jason R. Coombs Lösung)

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)"

Ich habe dies als eine Datei namens "effpoptp" (kein einfacher Name) im Ordner "/ bin" auf meinem Computer gespeichert, so dass es wie folgt getestet wird:

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

Der Zweck besteht darin, MySQL Workbench-Dateien zu versionieren, wobei die Datei die xml-Datei namens workbench-Datei oder die vollständige workbench-Datei sein kann.


1
2017-11-13 18:01





Das einfachste übliche Dienstprogramm, das verfügbar ist, ist dies jar, die davon ausgehen, dass STDIN verwendet wird, wenn Sie keine Dateiarg übergeben. Es braucht auch Argumente ähnlich wie die tar Programm für Operationen.

z.B. listet den Inhalt eines Archivs auf

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

Während Java nicht immer installiert ist, jar ist definitiv die bequemste Methode, dies zu tun.


1
2018-06-04 12:15