opscape

Archives and compression

unzip

List, test or extract the files in a .zip archive.

unzip [OPTION...] ARCHIVE[.zip] [MEMBER...] [-x EXCLUDE...] [-d DIR]

11 of 11 examples run in Debian 13.7 on 2026-10-31 · manual: unzip(1)

unzip archive.zip extracts everything into the current directory, recreating the stored paths. The everyday additions are -l to look before you extract, -d DIR to extract somewhere else, and member names (or patterns) to pull out only some files.

When a file already exists, unzip stops to ask whether to replace it. That is fine at a terminal and a trap in scripts, where there is nobody to answer: decide up front with -o (overwrite) or -n (never overwrite).

The command line has a fixed shape: options, the archive, then optional member names; -x and its exclusion patterns come after those, and -d DIR is accepted almost anywhere. Patterns like '*.csv' are matched by unzip itself against the stored names, so quote them.

Examples

List an archive's contents

Setup run before this example
zip -qr project.zip src data
unzip -l project.zip 'data/*.csv'
explain
output
Archive:  project.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
      436  2026-10-27 08:26   data/users.csv
      405  2026-10-26 08:37   data/sales.csv
---------                     -------
      841                     2 files

-l shows each member's size, date and path without extracting. The quoted pattern limits the listing to the CSV files under data/.

Extract into a directory with -d

Setup run before this example
zip -qr project.zip src data
unzip -q project.zip -d restore
ls restore restore/src
output
restore:
data
src

restore/src:
Makefile
app.py
lib
main.c
util.sh

-d restore creates the directory if needed and extracts there. -q suppresses the inflating: line per file.

Extract with the default per-file report

Setup run before this example
zip -qr src.zip src
unzip src.zip -d out
explain
output
Archive:  src.zip
   creating: out/src/
  inflating: out/src/main.c          
   creating: out/src/lib/
  inflating: out/src/lib/helpers.py  
  inflating: out/src/util.sh         
  inflating: out/src/Makefile        
  inflating: out/src/app.py          

Without -q, unzip names each item: creating: for directories, inflating: for compressed files (extracting: for stored ones).

Extract a single member

Setup run before this example
zip -qr project.zip src data
rm -r src data
unzip project.zip data/hosts.txt
cat data/hosts.txt
output
Archive:  project.zip
  inflating: data/hosts.txt          
web01 10.0.0.11
web02 10.0.0.12
db01 10.0.0.21
cache01 10.0.0.31

Name the member exactly as unzip -l shows it. Only that file is extracted, with its directory.

Extract everything except some files

Setup run before this example
zip -qr project.zip src data
unzip -q project.zip -x 'data/*' '*.py' -d out
find out -type f
output
out/src/main.c
out/src/util.sh
out/src/Makefile

Every pattern after -x is excluded, up to the next option. Here the whole data/ tree and both Python files are skipped.

Print a member to standard output

Setup run before this example
zip -qr project.zip data
unzip -p project.zip data/users.csv | cut -d, -f2 | head -n 4
explain
output
name
Alice Moreau
Bob Okafor
Chen Wei

-p writes the file's contents to standard output with no headers, ready for a pipeline.

Test an archive's integrity

Setup run before this example
zip -qr project.zip src
unzip -t project.zip
explain
output
Archive:  project.zip
    testing: src/                     OK
    testing: src/util.sh              OK
    testing: src/lib/                 OK
    testing: src/lib/helpers.py       OK
    testing: src/app.py               OK
    testing: src/Makefile             OK
    testing: src/main.c               OK
No errors detected in compressed data of project.zip.

-t decompresses every member in memory and checks its CRC, printing OK per file and a summary line.

Just the member names

Setup run before this example
zip -qr project.zip src
unzip -Z1 project.zip
explain
output
src/
src/app.py
src/Makefile
src/main.c
src/util.sh
src/lib/
src/lib/helpers.py

-Z switches unzip into zipinfo mode, and -1 prints bare names, one per line: the easiest format to loop over in a script.

Overwrite without asking in a script

Setup run before this example
zip -qr project.zip src
echo '// local edit' >> src/main.c
unzip -o project.zip src/main.c
tail -n 2 src/main.c
output
Archive:  project.zip
  inflating: src/main.c              
    return 0;
}

-o replaces existing files without a prompt, so the local edit is gone and main.c is back to the archived version.

What happens when nobody answers the prompt

Setup run before this example
zip -qr project.zip src
unzip project.zip src/main.c
explain
outputexit 1
Archive:  project.zip
replace src/main.c? [y]es, [n]o, [A]ll, [N]one, [r]ename:  NULL
(EOF or read error, treating as "[N]one" ...)

src/main.c exists, so unzip asks replace src/main.c?. Standard input is empty here, as in a cron job, so unzip treats it as "none", extracts nothing and exits with 1. Use -o or -n in scripts.

Asking for a member that is not there

Setup run before this example
zip -qr project.zip src
unzip project.zip nope.txt
explain
outputexit 11
Archive:  project.zip
caution: filename not matched:  nope.txt

unzip reports filename not matched and exits with 11, its status for "no matching files".

Common pitfalls

  • unzip x.zip *.txt lets the shell expand *.txt against local files first. Quote the pattern: unzip x.zip '*.txt'.

  • Archives made on Windows sometimes have no top-level folder and spill files into the current directory. List with -l first, or always extract with -d.

  • In scripts, an existing file makes unzip wait for an answer or fail. Pass -o or -n explicitly.

  • Info-ZIP unzip 6.0 struggles with some non-ASCII file names and very large (zip64) archives created elsewhere; bsdtar -xf file.zip or 7z x are alternatives.

GNU vs BSD and macOS

The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).

  • Linux and macOS both ship Info-ZIP unzip 6.0, so options match. macOS also has ditto -x -k and bsdtar, which extract zips too.

Options worth knowing

A selection, described in our own words. For the full list, see unzip(1) or unzip --help.

OptionWhat it does
-lList the archive's members with sizes and dates.
-vList verbosely, with compression method, ratio and CRC.
-tTest the integrity of each member.
-d DIRExtract into DIR (created if missing).
-x PATTERNExclude members matching the patterns that follow.
-oOverwrite existing files without asking.
-nNever overwrite existing files.
-qQuiet: do not print the per-file lines (-qq for even less).
-pExtract members to standard output with no messages.
-cExtract to standard output with the file names shown.
-jJunk paths: extract every file into one directory.
-uExtract only files that are newer than existing ones, or missing.
-fFreshen: replace existing files that are older; create nothing new.
-P PASSWORDSupply the password on the command line (visible to other users; avoid).
-ZBehave like zipinfo; -Z1 prints bare member names.
-LConvert names from uppercase-only systems to lowercase.

Related