23

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.

chillvibes
  • 331
  • 1
  • 2
  • 4

5 Answers5

15

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

Saftever
  • 331
  • 3
  • 4
10

Use bsdtar from libarchive:

> curl 'https://example.com/some.zip' | bsdtar -xOf - | less
4

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

shodanshok
  • 52,255
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
0

Uncompressing (with redirect to file):

cat file.gz | gunzip -c - > file

Compressing (with redirect to file.gz)):

cat file | gzip -c - > file.gz
chicks
  • 3,915
  • 10
  • 29
  • 37
TomOnTime
  • 8,381