19

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.

5 Answers 5

13

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 -.

7

Use bsdtar from libarchive:

> curl 'https://example.com/some.zip' | bsdtar -xOf - | less
2
  • 1
    For Cygwin, bsdtar has its own package bsdtar. Jan 4, 2022 at 9:53
  • bsdtar drops permissions when reading the archive from stdin.
    – 0xF2
    Jan 9 at 7:14
2

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

7
  • 14
    Wrong asnwer: zcat doesn't work with zip files! This answer should be downvoted. A solution can be found here using jar though: unix.stackexchange.com/questions/2690/…
    – Eric
    Apr 20, 2018 at 11:53
  • @Eric on my CentOS 6 box, I surely can use zcat file.zip to show zipped files. For example: file services.zip returns services.zip: Zip archive data, at least v2.0 to extract, and I can zcat service.zip to show its content
    – shodanshok
    Apr 20, 2018 at 21:18
  • 5
    Nope, 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 so zcat can't jump to the end of file to retrieve the files list. So in a nutshell zcat (actually gunzip since zcat calls it) doesn't work with zip files except when they contain only one file. Try it, you'lls see.
    – Eric
    Apr 22, 2018 at 19:02
  • 5
    I 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 on stdout, when you can not tell were is start/end of each file?
    – shodanshok
    Apr 23, 2018 at 5:21
  • @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.
    – user829755
    Aug 20, 2020 at 6:54
1

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
-1

Uncompressing (with redirect to file):

cat file.gz | gunzip -c - > file

Compressing (with redirect to file.gz)):

cat file | gzip -c - > file.gz
3
  • 8
    zip 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.
    – Eric
    Apr 20, 2018 at 11:51
  • 1
    This guy... zcat and gunzip do handle zip files, as long as the zip file only contains a single file, which is the case for this question. This answer is not the simplest but does answer the question and does not deserve downvotes.
    – tremby
    Sep 15, 2022 at 21:14
  • Only some versions of gzip support ZIP files, so this at least needs to contain a clarification of what gzip versions this works with (or even better, on which OSes these are commonly found).
    – lxgr
    Sep 15 at 17:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .