Archives and compression
unzip
List, test or extract the files in a .zip archive.
unzip [OPTION...] ARCHIVE[.zip] [MEMBER...] [-x EXCLUDE...] [-d DIR]
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 dataunzip -l project.zip 'data/*.csv'
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 dataunzip -q project.zip -d restore
ls restore restore/src
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 srcunzip src.zip -d out
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 dataunzip project.zip data/hosts.txt
cat data/hosts.txt
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 dataunzip -q project.zip -x 'data/*' '*.py' -d out
find out -type f
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 dataunzip -p project.zip data/users.csv | cut -d, -f2 | head -n 4
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 srcunzip -t project.zip
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 srcunzip -Z1 project.zip
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 srcecho '// local edit' >> src/main.c
unzip -o project.zip src/main.c
tail -n 2 src/main.c
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 srcunzip project.zip src/main.c
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 srcunzip project.zip nope.txt
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 *.txtlets the shell expand*.txtagainst 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
-lfirst, or always extract with-d.In scripts, an existing file makes unzip wait for an answer or fail. Pass
-oor-nexplicitly.Info-ZIP unzip 6.0 struggles with some non-ASCII file names and very large (zip64) archives created elsewhere;
bsdtar -xf file.zipor7z xare 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 -kand 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.
| Option | What it does |
|---|---|
-l | List the archive's members with sizes and dates. |
-v | List verbosely, with compression method, ratio and CRC. |
-t | Test the integrity of each member. |
-d DIR | Extract into DIR (created if missing). |
-x PATTERN | Exclude members matching the patterns that follow. |
-o | Overwrite existing files without asking. |
-n | Never overwrite existing files. |
-q | Quiet: do not print the per-file lines (-qq for even less). |
-p | Extract members to standard output with no messages. |
-c | Extract to standard output with the file names shown. |
-j | Junk paths: extract every file into one directory. |
-u | Extract only files that are newer than existing ones, or missing. |
-f | Freshen: replace existing files that are older; create nothing new. |
-P PASSWORD | Supply the password on the command line (visible to other users; avoid). |
-Z | Behave like zipinfo; -Z1 prints bare member names. |
-L | Convert names from uppercase-only systems to lowercase. |
Related
zipPackage and compress files into a .zip archive, the format every operating system opens natively.tarBundle files and directories into one archive, list it, or extract it; optionally compressed with gzip, bzip2, xz or zstd.gzipCompress files to .gz (replacing the original by default), or decompress them with -d or gunzip.