Unzip from stdin to stdout - funzip, python
Solution 1
Repost of my answer:
BusyBox's unzip
can take stdin and extract all the files to stdout. For example, when you use wget
as stdin,
wget -qO- http://downloads.wordpress.org/plugin/akismet.2.5.3.zip | busybox unzip -p -
-p
to extract files to pipe. The dash after is to use stdin as input.
You also can, (just like previous answer)
cat file.zip | busybox unzip -p -
But that's just redundant of unzip -p file.zip
.
If your distro uses BusyBox by default (e.g. Alpine), just run unzip -p -
.
Solution 2
Use bsdtar
from libarchive
:
> curl 'https://example.com/some.zip' | bsdtar -xOf - | less
Solution 3
Simply use zcat
. For example:
cat file.zip | zcat
Please note that in the example above the first part (cat file.zip
) is redundant, in the sense that you can simply issue zcat file.zip
and have the same results. I included it only to show that zcat
is capable to read from stdin
Solution 4
regarding stdout: unzip supports that out of the box with its -c and -p options. regarding stdin: Eric pointed out that the zip format has its directory at the end of the file, so the only way to make it streamable is to copy the input to a temporary storage. The following simple script does that:
#!/bin/bash
# usage: unzipOnTheFly [unzipArgs]
# unzipArgs: additional args to be passed to unzip
tmpFile=/tmp/unzipOnTheFly.$$.zip
cat >$tmpFile
unzip -p $tmpFile "$@"
rm $tmpFile
In the above case the solution would be
<file.zip unzipOnTheFly
If the archive contains more than one file and you want only one you can say
<file.zip unzipOnTheFly pathToOneFile
Related videos on Youtube
chillvibes
Updated on September 18, 2022Comments
-
chillvibes over 1 year
The goal is to read a zip file from stdin and uncompress to stdout.
Funzip works and is the solution I am looking for, the zip contains a single file, unfortunately funzip fails when the compressed file size is around 1GB or greater:
funzip error: invalid compressed data--length error
Update: I have discovered the above error may not indicate an actual error. Comparing two uncompressed files, one unzipped traditionally and the other through a pipe using funzip (with the above error written to stderr) the files are identical. I'd like to keep this open, so this can be confirmed or reported.
A related solution using python: Unzipping files that are flying in through a pipe
However this output is directed to a file.
-
Eric about 6 yearszip ang gzip are not the same thing. zip files stores the list of files at the end of the stream which makes it impractical for piping in while downloading. gzip doesn't have that limitation. This answer should be downvoted.
-
shodanshok about 6 years@Eric on my CentOS 6 box, I surely can use
zcat file.zip
to show zipped files. For example:file services.zip
returnsservices.zip: Zip archive data, at least v2.0 to extract
, and I canzcat service.zip
to show its content -
Eric about 6 yearsNope, it doesn't work on CentOS 6.9 when using a zip file that contains more than one file. I get
gzip: zip file has more than one entry--rest ignored
which is totally understandable since piping creates a stream and a stream is not seekable sozcat
can't jump to the end of file to retrieve the files list. So in a nutshellzcat
(actuallygunzip
sincezcat
calls it) doesn't work with zip files except when they contain only one file. Try it, you'lls see. -
shodanshok about 6 yearsI was under the impression that OP really want to output to
stdout
a single zipped file, not an entire zip archive. After all, what is the point of showing multiple, concatenated files onstdout
, when you can not tell were is start/end of each file? -
user829755 over 3 years@shodanshok, the point is you can add a filename from the list as cmd line argument to unzipper so that the output contains only that file. Yet as Eric pointed out that doesn't work with unzip if the input is a stream.
-
Jean-Pierre Matsumoto over 2 yearsFor Cygwin, bsdtar has its own package
bsdtar
.