Create a ZIP Archive of a Folder in Python

Recursively zip all files in a folder into a single archive using the standard library zipfile and pathlib modules.

Medium Python 3.9+ Aug 9, 2026 Files & data 16 views 0 copies

Python code

27 lines
Python 3.9+
import zipfile
from pathlib import Path

def zip_folder(source_dir: str, archive_path: str) -> None:
    """Zip all files in source_dir recursively into archive_path."""
    source = Path(source_dir)
    with zipfile.ZipFile(archive_path, "w", zipfile.ZIP_DEFLATED) as archive:
        for file_path in source.rglob("*"):
            if file_path.is_file():
                # Store files relative to source directory
                archive.write(file_path, file_path.relative_to(source))

if __name__ == "__main__":
    # Create a test directory with some sample files
    test_dir = Path("sample_folder")
    test_dir.mkdir(exist_ok=True)
    (test_dir / "readme.txt").write_text("Hello, world!")
    (test_dir / "data.csv").write_text("name,value\nAlice,42\nBob,17\n")
    sub_dir = test_dir / "subfolder"
    sub_dir.mkdir(exist_ok=True)
    (sub_dir / "config.json").write_text('{"enabled": true}')

    # Zip the folder and print the contents of the archive
    zip_folder("sample_folder", "sample_folder.zip")
    with zipfile.ZipFile("sample_folder.zip") as archive:
        for name in archive.namelist():
            print(name)

Output

stdout
readme.txt
data.csv
subfolder/config.json

How it works

The Path.rglob("*") method walks the source directory recursively, yielding every file and directory. Only regular files are written to the archive, using archive.write(file_path, file_path.relative_to(source)) to store paths relative to the source root — this keeps the archive tidy and portable. zipfile.ZIP_DEFLATED enables compression for smaller archives. The context manager ensures the archive is properly closed and flushed to disk even if an error occurs.

Common mistakes

  • Forgetting to filter for `is_file()`, which causes directory entries to be written with errors
  • Using absolute paths in `arcname`, which bloats the archive with full filesystem paths
  • Not specifying `ZIP_DEFLATED`, which leaves the archive uncompressed and much larger
  • Using `rglob` on a source path with trailing slashes, which can produce inconsistent relative names

Variations

  1. Use `shutil.make_archive("sample_folder", "zip", "sample_folder")` for a one-liner alternative
  2. Add a `filter` to rglob, e.g. `source.rglob("*")` → `(p for p in source.rglob("*") if p.suffix in {".txt", ".csv"})`, to zip only certain file types

Real-world use cases

  • Packaging project directories or logs for backup and offsite storage before a deployment.
  • Creating downloadable artifacts from build outputs or test fixtures in CI pipelines.
  • Bundling configuration files and assets for a microservice into a single deployable bundle.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Files & data

Related tutorials and quizzes for this topic.