Skip to content
Latchkey

zip -r: Recursively Archive a Directory

zip -r walks a directory tree and adds every file it finds into the archive.

Packaging a build output folder is the most common reason CI calls zip. Without -r, zip stores only the named entries and skips the contents of directories.

What it does

zip -r recursively traverses the named directories and adds all files and subdirectories to the archive, recreating the relative paths inside the zip. Paths are stored relative to the current working directory unless you cd into the directory first.

Common usage

Terminal
zip -r build.zip dist
# archive several inputs into one zip
zip -r release.zip dist config README.md
# store paths relative to dist by entering it first
cd dist && zip -r ../build.zip . && cd -

Options

FlagWhat it does
-rRecurse into directories
-r0Recurse but store without compression
<archive>First non-flag argument is the output zip
<files...>Inputs to add; directories need -r
-qQuiet, suppress the per-file listing

In CI

The path you pass becomes the path inside the zip. Running zip -r build.zip dist nests everything under a dist/ folder; cd into dist and zip . if you want the files at the archive root, which most extractors and deploy targets expect.

Common errors in CI

"zip: command not found" means the zip package is not preinstalled, which is common on slim container images and some self-hosted runners; install it (apt-get install -y zip on Debian/Ubuntu, apk add zip on Alpine). "zip warning: name not matched" means the input path does not exist relative to the current directory. Adding a directory without -r silently stores only the empty directory entry, producing an archive missing its contents.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →