Can I make unzip or any similar programs work on the standard output? The situation is I'm downloading a zip file, which is supposed to be unzipped on the fly.
Related issue: How do I pipe a downloaded file to standard output in bash?
Can I make unzip or any similar programs work on the standard output? The situation is I'm downloading a zip file, which is supposed to be unzipped on the fly.
Related issue: How do I pipe a downloaded file to standard output in bash?
While a zip file is in fact a container format, there's no reason why it can't be read from a pipe (stdin) 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 script can be minified to one line and created as an alias.
Now unzip the output of wget easily.
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:
You might have some luck with funzip.
I like to use curl because it is installed by default (the
-L
is needed for redirects which often occur):However,
bsdtar
is not installed by default, and I could not getfunzip
to work.This is a repost of my answer to a similar question:
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:
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 bygzip
andtar
kind of tools with a-
argument. But the standardunzip
does not do that (though, it does support extraction to a pipe). However, all is not lost...Look at funzip manual page.
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,however, no such update is seen around. I suspect that Mark found it unnecessary since other archiving methods worked easily with TAR.
Repost of my answer:
BusyBox's
unzip
can take stdin and extract all the files.The dash after
unzip
is to use stdin as input.You can even,
But that's just redundant of
unzip file.zip
.If your distro uses BusyBox by default (e.g. Alpine), just run
unzip -
.The simplest common utility available that will do this is
jar
, which will presume STDIN is being used if you pass it no file args. It also takes arguments similar to thetar
program for operations.e.g. list the content of an archive
curl https://my.example.com/file.zip | jar t
While Java is not always installed, on those machines where it is,
jar
is definitely the most convenient method of doing this.It's not possible with Info-Zip which is the most common OSS implementation. More importantly though, it's not recommended due to the constructs of ZIP archives.
If a change of format is viable to you then consider using tar(1) instead. It is quite happy with streamed input/output and, in fact, expects it by default.
Additionally you can often tell whether applications expect streamed input/output by specifying "-" for a filename. Info-Zip, as you can imagine, doesn't treat this as a valid argument.
In zsh, you can do the following:
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)
I saved this as a file named "effpoptp" (not a simple name) in the "/bin" folder on my machine so testing it is like so:
The purpose is to version control MySQL Workbench files, where the file could be the xml file named as the workbench file, or the complete workbench file.