zip Command: Compress Folders, Extract with unzip, and Compression Options
The zip command bundles files and folders on Linux into a single compressed zip file, and unzip is the companion command for extracting it. On an AlmaLinux 9 server, compressing a website folder with zip -r shrank 35,825 bytes to 4,158 bytes, and unzip -O fixed the garbled file names in a zip file made on Windows.
The output below comes from a working folder on an AlmaLinux 9.8 server, run as root, with times in UTC. The site folder and note files that were compressed are sample files made for the test. The zip made on Windows was reproduced with a test file whose file names were stored in CP949.
1️⃣ How to use the zip command
After zip, write the name of the new zip file first, then list the files to put in it. The command below compresses two files, readme.txt and memo.txt, into a single notes.zip.
zip notes.zip readme.txt memo.txt adding: readme.txt (deflated 92%)
adding: memo.txt (stored 0%)The [deflated 92%] at the end of a line is how much smaller the file became compared with its original size. The [stored 0%] on the line for the 71-byte memo.txt means the file was stored at its original size without compression.
To compress a folder, add -r. If you give only the folder name without -r, the archive holds just the folder entry site/ and none of the files inside it.
zip nodir.zip site adding: site/ (stored 0%)The site folder to compress has three subfolders and six files, as shown below.
With -r, all ten entries go in: the subfolders, the files inside them, and even .htaccess, whose name starts with a dot.
zip -r site.zip site adding: site/ (stored 0%)
adding: site/css/ (stored 0%)
adding: site/css/style.css (deflated 93%)
adding: site/js/ (stored 0%)
adding: site/js/app.js (deflated 87%)
adding: site/logs/ (stored 0%)
adding: site/logs/access.log (deflated 94%)
adding: site/index.html (deflated 91%)
adding: site/about.html (deflated 87%)
adding: site/.htaccess (deflated 9%)To see what a finished zip file contains without extracting it, use unzip -l. The stored files added up to 35,825 bytes, while ls -l showed site.zip at 4,158 bytes.
unzip -l site.zipArchive: site.zip
Length Date Time Name
--------- ---------- ----- ----
0 10-28-2026 22:10 site/
0 10-28-2026 22:10 site/css/
4431 10-28-2026 22:10 site/css/style.css
0 10-28-2026 22:10 site/js/
1882 10-28-2026 22:10 site/js/app.js
0 10-28-2026 22:10 site/logs/
24134 10-28-2026 22:10 site/logs/access.log
3723 10-28-2026 22:10 site/index.html
1612 10-28-2026 22:10 site/about.html
43 10-28-2026 22:10 site/.htaccess
--------- -------
35825 10 filesls -l site.zip-rw-r--r-- 1 root root 4158 Oct 28 23:05 site.zip2️⃣ zip command options
Among the zip command options, -x leaves out files that match a pattern. Specifying [site/logs/*] to skip the log folder leaves out the logs folder and access.log, so only eight entries go in.
zip -r site-nolog.zip site -x 'site/logs/*' adding: site/ (stored 0%)
adding: site/css/ (stored 0%)
adding: site/css/style.css (deflated 93%)
adding: site/js/ (stored 0%)
adding: site/js/app.js (deflated 87%)
adding: site/index.html (deflated 91%)
adding: site/about.html (deflated 87%)
adding: site/.htaccess (deflated 9%)Wrap the pattern in single quotes so the shell does not expand [*] into file names first. For the same purpose, the official manual gives an example with a backslash in front of [*].
-u puts back only the files that changed after the zip file was made. After adding one line to the end of index.html, running with -ru re-adds just that one file as [updating].
zip -ru site.zip siteupdating: site/index.html (deflated 90%)Running the same command again with nothing changed printed nothing, and the exit code was 12. In the official manual, 12 means zip has nothing to do.
zip -ru site.zip site; echo $?12To delete entries inside a zip file, use -d. Specifying [site/logs/*] removes the logs folder entry and access.log from site.zip.
zip -d site.zip 'site/logs/*'deleting: site/logs/
deleting: site/logs/access.logThe numbers -0 to -9 set the compression level, and the default is -6 according to the official manual. The same site folder was compressed three times with -q, which prints nothing, to compare sizes. Because one line had been added to index.html during the -u test, the original files now total 35,875 bytes.
zip -qr -0 level0.zip sitezip -qr level6.zip sitezip -qr -9 level9.zip sitels -l level*.zip-rw-r--r-- 1 root root 37433 Oct 28 23:05 level0.zip
-rw-r--r-- 1 root root 4179 Oct 28 23:05 level6.zip
-rw-r--r-- 1 root root 3874 Oct 28 23:05 level9.zip| Compression level | zip file size | vs. original total |
|---|---|---|
| Original file total | 35,875 bytes | 100% |
| -0 (no compression) | 37,433 bytes | 104.3% |
| -6 (default) | 4,179 bytes | 11.6% |
| -9 (maximum compression) | 3,874 bytes | 10.8% |
The 37,433 bytes made with -0 were larger than the 35,875-byte original total. That is the uncompressed data plus 1,558 bytes of header information, such as file names and times, attached to each entry. -9 came out 305 bytes smaller than the default, and the whole difference came from the largest file, access.log.
To set a password, add -e. You type the password twice, and the characters you type do not appear on the screen.
zip -e secret.zip memo.txtEnter password:
Verify password:
adding: memo.txt (stored 0%)Even secret.zip, made with -e, showed its file names, sizes and dates under unzip -l without a password. Only the file contents are encrypted, so it does not suit material whose file names must stay hidden too.
unzip -l secret.zipArchive: secret.zip
Length Date Time Name
--------- ---------- ----- ----
71 10-28-2026 22:10 memo.txt
--------- -------
71 1 file-P, which puts the password right on the command line, is an option the official manual warns is insecure, because other users on the same server can see running commands. The manual also describes zip's standard encryption itself as relatively weak.
When extracting a zip made with -e, unzip asks for the password for each file, and the file is extracted once you enter it correctly.
unzip secret.zip -d decArchive: secret.zip
[secret.zip] memo.txt password:
extracting: dec/memo.txt📌 Main options: results from this article
| Option | Task | Result in this article | |
|---|---|---|---|
| zip -r | Includes all subfolders and files inside the folder | Without -r, one line adding: site/; with -r, ten entries including .htaccess | |
| zip -x | Leaves out files that match a pattern | With site/logs/* left out, only eight entries, without the logs folder and access.log | |
| zip -u | Re-adds only the files that changed after the zip file was made | One line updating: site/index.html (deflated 90%); with nothing changed, no output and exit code 12 | |
| zip -d | Deletes entries inside the zip file | deleting: site/logs/ and deleting: site/logs/access.log | |
| zip -q | Hides the lines printed while compressing | All three commands compressed with -qr (-0, default, -9) finished without adding lines | |
| zip -0 | Stores files without compressing them | level0.zip at 37433 bytes, larger than the original file total | |
| zip -9 | Compresses as small as possible (default -6) | level9.zip 3874 bytes; level6.zip, made with the default, 4179 bytes | |
| zip -e | Asks for a password and encrypts the contents | Asks Enter password: and Verify password:, then adding: memo.txt (stored 0%) | |
| unzip -l | Lists the stored entries without extracting | site.zip: 10 files, 35825 bytes in total | |
| unzip -d | Sets the folder to extract into and creates it if it does not exist | Starts with creating: restore/site/, and the site folder structure is extracted under restore | |
| unzip -o | Overwrites all existing files without asking | Five inflating lines with no prompt | |
| unzip -n | Skips existing files without asking | Nothing appears after the Archive: site.zip line | |
| unzip -t | Tests the compressed data without extracting | OK for each entry and No errors detected; the truncated broken.zip gives End-of-central-directory signature not found | |
| unzip -O | Sets the character encoding of file names inside the zip | With -O CP949, the garbled names show up as 보고서.txt and 견적서.txt (Korean for "report" and "quote") | |
| unzip -p | Sends the extracted contents to standard output instead of creating files | Only the two lines of .htaccess appear, and no file is created |
📎 Other options: per the official manual
| Option | Task | |
|---|---|---|
| zip -m | Deletes the original files and folders after compressing (it deletes them after the zip file is complete, and the official manual recommends using it with -T) | |
| zip -j | Stores only file names, without folder paths | |
| zip -y | Stores a symbolic link as a link instead of the file it points to | |
| zip -T | Tests the new zip file and leaves the original zip file unchanged if the test fails | |
| zip -f | Replaces only entries already in the zip file with changed files and adds no new files | |
| zip -i | Includes only files that match the given pattern | |
| zip -P | Puts the password right on the command line (the official manual warns it is insecure) | |
| unzip -j | Extracts only the files into one folder without creating the folder structure inside the zip | |
| unzip -x | Sets entries not to extract | |
| unzip -q | Hides the lines printed while extracting | |
| unzip -u | Extracts only files missing from the disk and files that are newer | |
| unzip -v | Adds compression method, compressed size, ratio and CRC to the listing |
3️⃣ How to use the unzip command
To extract a zip file on Linux, write the zip file name after unzip. Without -d to set a folder, the files are extracted into the current folder (according to the official manual), so this time the restore folder was specified.
unzip site.zip -d restoreArchive: site.zip
creating: restore/site/
creating: restore/site/css/
inflating: restore/site/css/style.css
creating: restore/site/js/
inflating: restore/site/js/app.js
inflating: restore/site/index.html
inflating: restore/site/about.html
inflating: restore/site/.htaccessIf the folder given with -d does not exist, unzip creates it, and the site folder structure is extracted beneath it as is.
Extracting again to the same place makes unzip stop at every file that already exists and ask whether to overwrite it. Choosing [N]one ends the extraction without overwriting any of the remaining files.
unzip site.zip -d restoreArchive: site.zip
replace restore/site/css/style.css? [y]es, [n]o, [A]ll, [N]one, [r]ename: NTo handle this without prompts, add -o or -n. -o overwrites every existing file, and -n skips existing files. Because the official manual lists -o as a dangerous option, first make sure the folder is safe to overwrite before adding -o.
unzip -o site.zip -d restoreArchive: site.zip
inflating: restore/site/css/style.css
inflating: restore/site/js/app.js
inflating: restore/site/index.html
inflating: restore/site/about.html
inflating: restore/site/.htaccessunzip -n site.zip -d restoreArchive: site.zipExtracting with -n where every file already exists prints nothing after the Archive line.
To extract only part of a zip file, put a path or pattern after the zip file name. Specifying [site/css/*] extracts only the css folder and style.css.
unzip site.zip 'site/css/*' -d partArchive: site.zip
creating: part/site/css/
inflating: part/site/css/style.css4️⃣ unzip errors
Test a zip file received from another server with unzip -t before extracting it. If the compressed data has no problems, each entry shows OK, and the last line reads [No errors detected].
unzip -t site.zipArchive: site.zip
testing: site/ OK
testing: site/css/ OK
testing: site/css/style.css OK
testing: site/js/ OK
testing: site/js/app.js OK
testing: site/index.html OK
testing: site/about.html OK
testing: site/.htaccess OK
No errors detected in compressed data of site.zip.A zip whose end was cut off by an interrupted transfer ended with [End-of-central-directory signature not found]. This is the result of testing with -t a broken.zip that kept only the first 2,000 bytes of site.zip, which had become 2,436 bytes after the logs entries were deleted with -d.
unzip -t broken.zipArchive: broken.zip
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
unzip: cannot find zipfile directory in one of broken.zip or
broken.zip.zip, and cannot find broken.zip.ZIP, period.unzip reads the file list at the very end of a zip file (the central directory) first. That is why it could not test even the first entry of broken.zip, whose end was cut off.
Giving it a file that is not a zip produced the same message. Opening site.tar.gz, bundled with tar, in unzip ended with the same error, and a tar.gz file is extracted with the tar command instead.
unzip site.tar.gzArchive: site.tar.gz
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
unzip: cannot find zipfile directory in one of site.tar.gz or
site.tar.gz.zip, and cannot find site.tar.gz.ZIP, period.A zip file made on Windows sometimes stores its file names in a Windows character encoding rather than UTF-8. When report-win.zip, whose names were stored in CP949, was opened with unzip -l on a UTF-8 server, the file names came out as unreadable symbols.
unzip -l report-win.zipArchive: report-win.zip
Length Date Time Name
--------- ---------- ----- ----
26 10-28-2026 22:10 ║╕░э╝н.txt
17 10-28-2026 22:10 ░▀└√╝н.txt
--------- -------
43 2 filesIf you write the character encoding of the Windows system that made the zip after -O, the names show up correctly, and files extracted with the same option are created with their original names.
unzip -O CP949 -l report-win.zipArchive: report-win.zip
Length Date Time Name
--------- ---------- ----- ----
26 10-28-2026 22:10 보고서.txt
17 10-28-2026 22:10 견적서.txt
--------- -------
43 2 filesunzip -O CP949 report-win.zip -d winArchive: report-win.zip
inflating: win/보고서.txt
inflating: win/견적서.txtAccording to the unzip help, -O is the option for zip files made on DOS or Windows, and -I is for zip files made on other systems.
The error messages that came up while extracting, and what to check next, are listed below.
| Output | Meaning | What to check next |
|---|---|---|
| End-of-central-directory signature not found | The file list at the end of the zip file was not found: the file is truncated or not a zip | Compare the size with the original and download it again · use tar for tar.gz |
| cannot find or open | No file with that name in the current folder | File name and location with ls |
| skipping: … incorrect password | The password was wrong three times, so that file was skipped (exit code 82) | Letter case of the password and the input language |
| File names garbled into symbols | Names stored in a Windows character encoding | That encoding (such as CP949) after -O |
🔲 zip command simulator
In the simulator below, you can type the steps yourself: compress with zip, then list or extract with unzip.
🔢 FAQ & Recommended Content
WordPress · Plugins
How to Install a WordPress Plugin: Search and Install, ZIP Upload and Activation
The steps for installing a plugin from the Add Plugins screen, either by searching the official directory or by uploading a zip file.
Search
Linux find command
The find command locates files by conditions such as name, extension, size and date, and then runs further actions on the files it finds.
File management
cp Command Options and Overwriting Files in Bulk
Options of the cp command for copying files and directories, and how to copy in bulk without overwrite prompts.
ℹ️ Affiliate Disclosure
This site's content contains affiliate links. When a visitor buys a product or service through one of them, the site receives a commission from the seller. The amount the buyer pays(it goes down during event discounts ↓)does not go up. Posted prices, discounts, and stock reflect the time of writing and may differ, so confirm with the seller before buying. Products are chosen and reviewed by our own standards, and commissions do not affect the order or content of reviews.