This seemed like it should be doable, but it looks like it's only possible to extract a zip and pipe the file to another command if the zip contains only a single file. I wanted to extract a specific file from a multi-file zip. Instead of piping, I switched to chaining multiple commands 'unzip file.zip /path/file && dostuff /path/file && rm -rf /path' While not answering the original question, and resulting in temporary files being created, it satisfied my need.
–
Stan KurdzielJul 18 '13 at 21:13

7 Answers
7

While a zip file is in fact a container format, there's no reason why it can't be read as a stream if the file can fit into memory easily enough. Here's a Python script that takes a zip file as standard input and extracts the contents to the current directory or to a specified directory if specified.

This is unlikely to work how you expect. Zip is not just a compression format, but also a container format. It rolls up the jobs of both tar and gzip.bzip2 into one. Having said that, if your zip has a single file, you can use unzip -p to extract the files to stdout. If you have more than one file, there's no way for you to tell where they start and stop.

As for reading from stdin, the unzip man page has this sentence:

Archives read from standard input are not yet supported, except with funzip (and then only the first member of the archive can be extracted).

What you want to do is, make unzip take a ZIPped file on its standard input rather than as an argument. This is usually easily supported by gzip and tar kind of tools with a - argument. But the standard unzip does not do that (though, it does support extraction to a pipe). However, all is not lost...

funzip without a file argument acts as a filter; that is, it assumes that a ZIP archive (or a gzip'd file) is being piped into standard
input, and it extracts the first member from the archive to stdout.
When stdin comes from a tty device, funzip assumes that this cannot be
a stream of (binary) compressed data and shows a short help text,
instead. If there is a file argument, then input is read from the
specified file instead of from stdin.

Given the limitation on single-member extraction, funzip is most useful
in conjunction with a secondary archiver program such as tar(1). The
following section includes an example illustrating this usage in the
case of disk backups to tape.

This goes well with the idea that most linux archives are usually TAR'ed and then ZIPped in some way (gzip, bzip, et al). This will work for you if you have a tar.ZIP.

It is worth noting that funzip is written by Info-ZIP original author Mark Adler. He writes in the funzip man page,

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

however, no such update is seen around. I suspect that Mark found it unnecessary since other archiving methods worked easily with TAR.

Just a comment; some people would like python or any language as an option to unzip. A prime example is Heroku which does not include tar or unzip on its system. A work around is to use jar by installing Java which is allowed.
–
NickNov 11 '14 at 20:37

I actually needed something a little more complex - extract a specific file if it exists. The difficulty being, the input file stream may not be a zip file, and in which case, I needed it to continue through the pipe. Here is my solution (thanks mostly to Jason R. Coombs solution)

The ZIP file format includes a directory (index) at the end of the archive. This directory says where, within the archive each file is located and thus allows for quick, random access, without reading the entire archive.

This would appear to pose a problem when attempting to read a ZIP archive through a pipe, in that the index is not accessed until the very end and so individual members cannot be correctly extracted until after the file has been entirely read and is no longer available. As such it appears unsurprising that most ZIP decompressors simply fail when the archive is supplied through a pipe.

The directory at the end of the archive is not the only location where file meta information is stored in the archive. In addition, individual entries also include this information in a local file header, for redundancy purposes.

Although not every ZIP decompressor will use local file headers when the index is unavailable, the tar and cpio front ends to libarchive (a.k.a. bsdtar and bsdcpio) can and will do so when reading through a pipe, meaning that the following is possible: