Home / Alt manpages / funzip(1)

  • funzip(1)
  • User command
  • linux

Extract the First ZIP Member from a Stream with funzip

You will finish with a repeatable way to send a ZIP or gzip stream through funzip and receive its first member on standard output. That makes it useful in pipelines where another command consumes the extracted data. The examples use Ubuntu's unzip package, version 6.0-28ubuntu4.1, installed on this system.

Allow about ten minutes. You need a shell, a readable archive, and a destination or downstream command that can accept the extracted bytes. The normal examples are unprivileged. Do not use sudo unless filesystem permissions, rather than funzip, require it.

1. Check the installed command

Confirm that the command is the one on your path and record the package version. These checks only read local metadata:

$ command -v funzip
/usr/bin/funzip
$ dpkg-query -W -f='${Package} ${Version}\n' unzip
unzip 6.0-28ubuntu4.1

The local manual describes the installed interface as funzip [-password] [input[.zip|.gz]]. With a file argument, the archive is read from that file. Without one, compressed data must arrive on standard input. If standard input is a terminal, funzip assumes you did not mean to type binary data and prints short help instead.

Checkpoint

You should have a readable funzip at /usr/bin/funzip and a package version to compare with this guide.

2. Extract the first member to a file

Give the archive as the input file and redirect standard output to a new destination:

$ funzip /path/to/archive.zip > extracted.bin
$ test -s extracted.bin && echo 'extracted data is non-empty'
extracted data is non-empty

The command writes the first member, not the whole archive and not every member. The member's original name is not used to choose your output name. Pick the destination yourself, particularly when the first member is binary data.

Redirection with > truncates an existing file before funzip starts. To protect an existing result, use a temporary name and replace it only after checking the exit status and content:

$ funzip /path/to/archive.zip > extracted.bin.new
$ status=$?
$ if [ "$status" -eq 0 ]; then mv extracted.bin.new extracted.bin; else rm extracted.bin.new; fi
$ printf 'funzip exit status: %s\n' "$status"
funzip exit status: 0

The rm here removes only the newly created temporary output after a failed extraction. Check the path before running a variation of this pattern. Do not point it at the original archive or an irreplaceable file.

3. Use funzip in a pipe

When another program already produces a ZIP stream, omit the input filename. This example sends a local archive through standard input:

$ cat /path/to/archive.zip | funzip > extracted.bin
$ cmp --silent extracted.bin expected.bin && echo 'first member matches expected data'
first member matches expected data

For a real producer, replace cat with the command that supplies the archive. Avoid displaying binary output directly in a terminal. If you only need to test decompression and do not want a result file, discard the output:

$ funzip /path/to/archive.zip > /dev/null
$ printf 'exit status: %s\n' "$?"
exit status: 0

A zero status means this invocation completed successfully. It does not mean that the first member is the file you intended, so inspect the archive before relying on a pipeline that has several members.

4. Inspect the archive before extracting

funzip has no option for selecting a later ZIP member. Use unzip -l to see the order and names without extracting anything:

$ unzip -l /path/to/archive.zip
Archive:  /path/to/archive.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
      ...  YYYY-MM-DD HH:MM   first-member
      ...  YYYY-MM-DD HH:MM   another-member
---------                     -------
      ...                     2 files

The lengths, dates and names depend on your archive. The first listed member is the one funzip attempts to extract. If the desired member is later in the list, use unzip with its member name instead. Do not try to solve that limitation by piping the archive repeatedly: a ZIP stream is not a queue of independent archives.

If the first member is a directory, the manual says that funzip creates the directory and exits. Treat that as a special case rather than expecting directory contents on standard output.

5. Handle gzip input and encrypted archives

The same filter also accepts a gzip-compressed input stream:

$ gzip -c /path/to/input.txt | funzip
contents of input.txt

For an encrypted ZIP whose first member needs a password, the usual interactive form prompts without echoing the password:

$ funzip /path/to/encrypted.zip > extracted.bin
password: [typed without echo]

Do not put a real password in a command copied into shell history or visible process listings. The manual permits a dash-prefixed password before the filename, but explicitly warns that this exposes the secret on systems where ps or history can be read. Prefer the prompt when the installed build supports the required decryption.

If a password prompt leaves the terminal with echo disabled, recover it by running the same command again with output redirected to /dev/null, entering the password at the prompt. The manual documents this as a terminal race that can occur when piping encrypted output into more. If the terminal remains unusable, start a fresh terminal session and investigate before entering credentials again.

6. Build a stream pipeline

The single-member rule is useful when the first member is itself a tar stream. A common shape is:

$ funzip backup.zip | tar tf -
./
./etc/
./etc/example.conf

Here funzip decompresses the first ZIP member and tar tf - lists the tar archive received on standard input. Listing is a safer first check than extracting. If the listing is correct, a separate extraction command can be run in a chosen directory. Do not extract an untrusted archive into a directory containing important files without reviewing its paths and contents first.

For a backup stream, the inverse shape is possible: a producer creates a tar stream, zip compresses it, and funzip passes the first member back to tar. Keep the output target explicit and verify each command's exit status in scripts; a pipeline's status rules depend on the shell and are not a substitute for checking the individual stages.

7. Diagnose the common failures

funzip reports an input error when the bytes are not a supported ZIP or gzip stream. Check the file type and path without changing the file:

$ file /path/to/archive.zip
$ test -r /path/to/archive.zip && echo readable
readable

If the command prints help rather than extracting, check whether you accidentally ran it with no pipe and no filename. If extraction stops after one member, that is expected behaviour, not a partial scan. Recheck the member order with unzip -l.

Keep the source archive until the output has been verified. When the output is text, inspect it with a pager or cmp; for binary data, use an appropriate format-aware tool. A successful decompression does not validate the application-level contents.

Done means

  • funzip and the installed unzip package version are confirmed.
  • You know that only the first ZIP member is extracted.
  • Your output destination is new or protected from accidental truncation.
  • A test command checks the exit status and, where useful, compares the output.
  • Encrypted input is handled with an interactive prompt rather than a visible password.
  • Any tar pipeline was listed or tested before an extraction that changes files.