Inspect ZIP Archives Safely with zipinfo
You will be able to inspect a ZIP archive's contents, identify useful metadata, select members by name, and produce script-friendly output without extracting anything. The examples use Info-ZIP ZipInfo 3.00 from the Ubuntu unzip package 6.0-28ubuntu4.1. Allow about 10 minutes if the archive is already on the machine.
The route
Jump straight to the step you need, or tick off Done means at the end.
Before you start
You need a shell and a readable ZIP archive. No root access is needed, and the commands in this guide do not modify the archive or the files around it. Replace /path/to/archive.zip with a real path. Keep the path quoted when it contains spaces or shell wildcard characters.
Check which program is installed and its version:
command -v zipinfo
zipinfo -h
The installed program is also available through unzip -Z. That is useful on a system where the separate zipinfo command is not present.
Checkpoint 1: list the archive
Start with the default listing. It shows one line per archive member, with a header and a totals line.
zipinfo "/path/to/archive.zip"
A typical entry looks like this:
-rw-r--r-- 3.0 unx 18 tx stor 26-Sep-28 15:47 demo/run.sh
The leading fields describe permissions, the version of the creating program, the originating file system, uncompressed size, a text or binary hint, extra-field or local-header markers, and the compression method. The date and member name come last. A directory is normally shown as a name ending in /.
The header reports the archive size and entry count. The totals line reports uncompressed and compressed data sizes. Those data totals are not the same as the archive's on-disk size because ZIP headers and other archive structures are included in the latter.
Checkpoint 2: choose the amount of detail
Use -1 when another command needs only member names. It deliberately removes headers, totals and comments.
zipinfo -1 "/path/to/archive.zip"
Use -l for a long listing that adds each member's compressed size. Use -m instead when a compression percentage is more useful.
zipinfo -l "/path/to/archive.zip"
zipinfo -m "/path/to/archive.zip"
Use -v for archive diagnostics, including central-directory details, comments and extra fields. It can be lengthy, so send it to a normal pager:
zipinfo -v "/path/to/archive.zip" | less
The built-in -M pager also works, but the manpage documents limitations with wrapped lines and screen size. A normal pager gives you familiar searching and quitting behaviour.
Checkpoint 3: inspect selected members
Put member names after the archive path to limit the listing. This is useful for checking a single configuration file or a small group of files.
zipinfo -m "/path/to/archive.zip" "config/app.conf"
zipinfo -mt "/path/to/archive.zip" "docs/*.md"
Quote the member pattern. The shell must not expand it against directories on the host machine. In the second command, -t adds totals for the selected members. Supplying member names normally suppresses the archive header and totals unless you request them explicitly.
To exclude members, add -x followed by the unwanted names or patterns:
zipinfo "/path/to/archive.zip" -x "node_modules/*" "*.cache"
Patterns are matched against names stored in the archive, not paths on your file system. If a pattern matches nothing, check the exact spelling with zipinfo -1. ZIP member names are case-sensitive in practice, and a stored directory prefix such as project/ is part of the name.
Dates, comments and machine-readable names
Add -T to print member times as yymmdd.hhmmss. That makes simple sorting more reliable than sorting human-readable month names.
zipinfo -T "/path/to/archive.zip" | sort -nr -k 7
This uses the default short format, where the timestamp begins in field 7. If you use -m or -l, the timestamp moves to field 8. Treat this as a quick inspection pipeline rather than a stable interchange format: filenames containing unusual whitespace can still make field-based parsing unsuitable.
Use -z when you need the archive comment. Use -h for the header and -t for totals. A common trap is that -h or -t on its own asks for only that line, rather than adding it to a full listing. Add a format option when you want members as well:
zipinfo -st "/path/to/archive.zip"
zipinfo -lht "/path/to/archive.zip"
Defaults that can surprise you
On Unix, ZIPINFO and the compatibility variable ZIPINFOOPT can add options to every invocation. An explicit command-line option has higher priority, but an inherited environment setting can still explain missing headers, totals or member lines.
env | grep -E '^(ZIPINFO|ZIPINFOOPT)='
env -u ZIPINFO -u ZIPINFOOPT zipinfo "/path/to/archive.zip"
Use the second command as a clean comparison when output looks wrong. Avoid placing a permanent preference in a shell profile until you understand its effect. In particular, a negated option such as --t disables the default totals line, and a command containing only -t can then print just totals.
Safety and failure checks
zipinfo reads archive metadata. It does not extract members, so these examples do not overwrite files. Do not treat a listing as proof that extraction is safe: archive names can contain absolute paths, parent-directory components or misleading names. If you later extract an untrusted archive, inspect its names first and use a dedicated directory, with extraction-specific safeguards.
For a missing or unreadable archive, check the path and permissions:
test -r "/path/to/archive.zip" && zipinfo "/path/to/archive.zip"
printf 'exit status: %s\n' "$?"
A non-zero exit status means the inspection did not complete successfully. Do not silence it with a pipe that hides the first command's status. For a damaged or incomplete ZIP, the diagnostic from zipinfo is more useful than a partial listing. Re-copy the archive from a trusted source and compare a checksum if integrity matters.
Done means
- You can list names with
zipinfo -1without extracting the archive. - You can choose short, medium, long or verbose metadata with
-s,-m,-lor-v. - You quote member patterns and understand that filters match stored archive names.
- You know that member filters change the default header and totals behaviour.
- You have checked for
ZIPINFOandZIPINFOOPTwhen output is unexpected.