ozip is a fast, parallel zip compression tool written in Go. Drop-in replacement for zip with smart defaults, powerful exclusion patterns, and production-ready reliability.

Contact us and let us know on how many servers you'd like to use it so you can get you a good price for it.

ozip vs zip: Full Comparison

Test Setup

testdir/
├── root.log
├── keep.txt
├── dir1/
│   ├── level1.log
│   └── dir2/
│       ├── level2.log
│       └── dir3/
│           ├── level3.log
│           └── level3.txt
├── logs/
│   └── app.log
└── deep/
    └── nested/
        └── path/
            └── file.LOG

Exclude Pattern Behavior

Behavior zip (Info-ZIP) ozip
Case sensitivity Case-sensitive Case-insensitive
* crosses / Yes No
Simple pattern (*.log) matches all levels Yes Yes (basename match)
Path pattern (dir1/*.log) Matches ALL depths under dir1/ Matches only dir1/level1.log
Trailing / = directory only No effect Yes
Regex support No Yes (--app-xr)

Test Results

Simple pattern: *.log

zip: Excludes root.log, level1.log, level2.log, level3.log, app.log. Does NOT exclude file.LOG (case-sensitive).

ozip: Excludes all of the above AND file.LOG (case-insensitive).

Path pattern: dir1/*.log — the key difference

zip: Excludes dir1/level1.log, dir1/dir2/level2.log, AND dir1/dir2/dir3/level3.log. The * crosses / boundaries, matching all .log files at any depth under dir1/.

ozip: Excludes only dir1/level1.log. The * stays within a single path segment (Go's filepath.Match behavior). To exclude all depths, use regex: --app-xr 'dir1/.*\.log$'.

Wildcard dir1/* — crosses all levels in zip

zip: dir1/* excludes the entire dir1/ subtree — all files and subdirectories at every depth.

ozip: dir1/* excludes only direct children of dir1/ (one level). For the full subtree, use dir1/ (trailing slash) or --app-xr 'dir1/'.

Case sensitivity: *.LOG

zip: Only excludes file.LOG. Does NOT exclude .log files.

ozip: Excludes ALL .log and .LOG files. Both pattern and path are lowercased before matching.

Directory-only: dir2/

zip: Trailing slash has no special effect. dir2/ did NOT exclude the dir2 directory — it was still included in the archive.

ozip: Trailing slash restricts the pattern to directories only. dir2/ excludes the directory and its entire subtree.

Summary

Where ozip improves on zip

Case-insensitive matching. A single -x '*.log' catches file.log, FILE.LOG, debug.Log, and every variation. On web servers where file naming is inconsistent, this prevents files from slipping through.

*Predictable `behavior.** In zip,dir1/.logsilently matches 3 levels deep. In ozip,always means one path segment — no surprises. When you need multi-level matching, use regex (--app-xr`) which makes the intent explicit.

Directory-only patterns. Trailing / in ozip excludes directories and their subtrees. In zip, trailing / has no effect — you need dir/* instead, which also crosses boundaries unpredictably.

Regex support. ozip's --app-xr flag provides full regex exclusions for complex patterns that globs can't express:

# Exclude all cache and backup directories
ozip --app-xr '(cache|backup|\.tmp)/' archive.zip .

# Exclude log files only in wp-content
ozip --app-xr 'wp-content/.*\.log$' archive.zip .

Where zip differs

*`crosses/boundaries.** This can be convenient (dir1/excludes the whole subtree) but also dangerous —.log` in a path pattern may match more files than expected at deeper levels.

Case-sensitive. Matches exactly what you type. Requires separate patterns for *.log and *.LOG if both exist.

Beyond Exclude Patterns

Compression

Feature zip (Info-ZIP) ozip
Parallel compression No (single-threaded) Yes (multi-core, configurable workers)
Compression levels 0-9 (level 6 default) 0-9 (level 6 default)
Smart store for compressed files No (re-compresses .jpg, .mp4, .gz) Yes (auto-detects and stores at level 0)
Streaming compression Buffered but single-pass Buffered I/O (256 KB) with parallel workers

zip uses a single thread. ozip uses all available CPU cores by default with a parallel pipeline: feeder -> N workers -> sequential writer. Each worker compresses independently using CreateRaw with pre-compressed data. On multi-core servers, ozip is significantly faster on large directory trees.

ozip auto-detects already-compressed files (.jpg, .png, .mp4, .gz, .zip, .rar, .woff2, .pdf, .docx, etc.) and stores them at level 0 instead of wasting CPU. zip re-compresses everything regardless.

Archive Operations

Feature zip (Info-ZIP) ozip
Update existing archive (-u) Yes Yes
Freshen existing files (-f) Yes Yes
Test archive integrity (-T) Yes Yes (CRC32 verification)
Password protection Yes (ZipCrypto, weak) Yes (via 7z: AES-256, .7z also encrypts filenames)
7z format support No Yes (delegates to external 7z binary)
Archive comment Yes (-z) Yes (--app-comment or OZIP_COMMENT)
Junk paths (-j) Yes Yes
Zip directory prefix No Yes (--app-zip-dir-prefix)
Stdout output Yes (-) Yes (-)

zip's built-in encryption uses ZipCrypto which is known to be weak and crackable. ozip delegates to 7z for AES-256 encryption. When using .7z format, filenames are also encrypted.

Reliability

Feature zip (Info-ZIP) ozip
Atomic writes on update No Yes (temp file + fsync + rename)
Signal cleanup No (leaves partial archive) Yes (SIGTERM/SIGINT removes partial file)
Disk space check No Yes (--app-check-disk-space)
File locking No Yes (shared read locks with 30s timeout)
fsync before reporting success No Yes
Self-exclusion No (can archive itself) Yes (auto-detects output file in source tree)

zip writes directly to the output. If the process is killed, you get a corrupted archive. ozip uses temp file + fsync + atomic rename for update/freshen operations, and removes partial archives on signal interrupt.

ozip automatically detects when the output archive is inside the source directory and excludes it. zip will happily include itself in the archive, causing corruption or infinite growth.

Automation

Feature zip (Info-ZIP) ozip
Lifecycle hooks No Yes (pre/post/complete/error)
Email notifications No Yes (--app-notify-email)
Dry run No Yes (--app-dry-run)
Progress output No Yes (--app-progress)
Nice level External (nice -n 10 zip ...) Built-in (--app-nice 10)
Quiet mode (-q) Yes Yes
Regex exclusions No Yes (--app-xr)
Environment variable config ZIPOPT for default flags Full config: OZIP_LEVEL, OZIP_WORKERS, OZIP_COMMENT, etc.

ozip hooks enable automated backup workflows:

ozip --app-pre-hook 'echo "Starting backup"' \
     --app-complete-hook 'rsync $OZIP_ARCHIVE remote:backups/' \
     --app-error-hook 'curl -X POST https://alerts.example.com' \
     --app-notify-email admin@example.com \
     --app-nice 10 \
     backup.zip /var/www

Deployment

Feature zip (Info-ZIP) ozip
Installation Package manager (apt install zip) Single static binary, zero dependencies
Self-update No Yes (ozip cli update)
Cross-platform binary Separate packages per OS Linux + macOS from single build script
Thread safety on constrained servers N/A (single-threaded) Auto-caps workers based on ulimit -u
Last updated 2008 (Zip 3.0) Actively maintained

Info-ZIP's last release was 2008. ozip is actively maintained with modern Go, parallel compression, and features designed for current server environments.

When to use zip

  • Maximum compatibility — zip is pre-installed on most systems
  • You need ZipCrypto encryption specifically (some legacy systems require it)
  • Simple one-off compression where speed doesn't matter

When to use ozip

  • Speed matters — parallel compression on multi-core servers
  • Large web sites with thousands of files (.jpg, .mp4 auto-detected)
  • Backup automation with hooks, email, error handling
  • Shared hosting with low ulimit -u — ozip auto-adjusts worker count
  • Stronger encryption (AES-256 via 7z)
  • You want case-insensitive, predictable exclude patterns
  • Single binary with self-update — no package manager needed

ozip vs tar: Full Comparison

Test Setup

tartest/
├── root.log
├── keep.txt
├── dir1/
│   ├── level1.log
│   └── dir2/
│       ├── level2.log
│       └── dir3/
│           ├── level3.log
│           └── level3.txt
├── logs/
│   └── app.log
└── deep/
    └── nested/
        └── path/
            └── file.LOG

Exclude Pattern Behavior

Behavior tar (bsdtar) ozip
Case sensitivity Case-sensitive Case-insensitive
* crosses / No No
Simple pattern (*.log) matches all levels Yes Yes (basename match)
Path pattern (dir1/*.log) Matches only dir1/level1.log Matches only dir1/level1.log
Trailing / = directory only Yes Yes
Regex support No Yes (--app-xr)

Test Results

Simple pattern: *.log

Both tar and ozip exclude .log files at every directory level.

tar: Excludes root.log, level1.log, level2.log, level3.log, app.log. Does NOT exclude file.LOG.

ozip: Excludes all of the above AND file.LOG (case-insensitive).

Path pattern: dir1/*.log

Both tar and ozip only match one level deep — * does not cross /.

tar: Excludes only dir1/level1.log. Does NOT exclude dir1/dir2/level2.log or deeper.

ozip: Same behavior. filepath.Match treats * as a single path segment.

Case sensitivity: *.LOG

tar: Only excludes file.LOG. Does NOT exclude root.log, level1.log, etc.

ozip: Excludes ALL .log and .LOG files. ozip lowercases both pattern and path before matching.

Directory-only: dir2/

tar: Excludes the entire dir2/ directory and its subtree.

ozip: Same behavior. Trailing / restricts the pattern to directories only.

Key Differences

Case-insensitive matching (ozip)

ozip always matches case-insensitively. This is intentional for web hosting environments where file naming is inconsistent (e.g. image.JPG, backup.Sql, FILE.LOG). A single -x '*.log' catches all variations.

tar requires --ignore-case (GNU tar only) or separate patterns for each case variation.

Regex support (ozip only)

ozip supports regex exclusions via --app-xr:

ozip --app-xr 'node_modules/' archive.zip .
ozip --app-xr '\.(log|tmp|bak)$' archive.zip .

tar has no built-in regex support for exclusions.

Suffix sliding (ozip)

For path patterns containing /, ozip tries the pattern against the full path and every suffix. This means */wp-content/*cache*/ matches public_html/wp-content/cache-fast/ even with extra leading segments.

tar matches the pattern against the member name as stored in the archive.

GNU tar vs bsdtar

GNU tar's default is --wildcards-match-slash for exclusions, meaning * can cross / boundaries. bsdtar (macOS) does NOT let * cross /. ozip behaves like bsdtar — * stays within a single path segment.

Beyond Exclude Patterns

Compression

Feature tar ozip
Format tar (uncompressed), tar.gz, tar.bz2, tar.xz zip, 7z (via external 7z binary)
Parallel compression No (single-threaded) Yes (multi-core, configurable workers)
Compression levels Depends on compressor (gzip -1 to -9) 0-9 (level 6 default)
Smart store for compressed files No Yes (auto-detects .jpg, .zip, .mp4, etc. and stores at level 0)

tar compresses with a single thread. ozip uses all available CPU cores by default, with a parallel pipeline: feeder goroutine -> N worker goroutines -> sequential writer. On a 4-core machine compressing a large site, ozip can be 3-4x faster.

ozip auto-detects already-compressed files (.jpg, .png, .mp4, .gz, .zip, etc.) and stores them at level 0 instead of wasting CPU trying to recompress them.

Archive Operations

Feature tar ozip
Update existing archive (-u) Yes Yes
Freshen existing files (-f) No Yes (only replace older, no new files)
Test archive integrity (-T) No built-in Yes (CRC32 verification)
Password protection No Yes (via 7z backend)
Archive comment No Yes (--app-comment)
Junk paths (-j) No Yes (store files without directory structure)
Zip directory prefix No Yes (--app-zip-dir-prefix)

Reliability

Feature tar ozip
Atomic writes No (partial file on interrupt) Yes (temp file + rename)
Signal cleanup No (leaves partial archive) Yes (SIGTERM/SIGINT removes partial archive)
Disk space check No Yes (--app-check-disk-space)
File locking No Yes (shared read locks with timeout)
fsync before reporting success No Yes

tar writes directly to the output file. If interrupted (Ctrl+C, kill), you get a partial corrupted archive. ozip writes to a temp file first, calls fsync, then atomically renames. On interrupt, the signal handler removes the partial temp file — you never get a half-written archive.

Automation

Feature tar ozip
Lifecycle hooks No Yes (pre/post/complete/error)
Email notifications No Yes (--app-notify-email)
Dry run No Yes (--app-dry-run)
Progress output No Yes (--app-progress)
Nice level External (nice -n 10 tar ...) Built-in (--app-nice 10)
Environment variable config No Yes (OZIP_LEVEL, OZIP_WORKERS, etc.)

ozip hooks run shell commands at key lifecycle points and receive environment variables (archive path, file count, bytes written, elapsed time). This enables cron-based backup workflows:

ozip --app-pre-hook 'echo "Starting backup"' \
     --app-complete-hook 'rsync $OZIP_ARCHIVE remote:backups/' \
     --app-error-hook 'curl -X POST https://alerts.example.com' \
     --app-notify-email admin@example.com \
     backup.zip /var/www

Deployment

Feature tar ozip
Installation Pre-installed on all Unix systems Single static binary, zero dependencies
Self-update No Yes (ozip cli update)
Cross-platform binary N/A Linux + macOS from single build script
Thread safety on constrained servers N/A Auto-caps workers based on ulimit -u

When to use tar

  • You need tar format specifically (e.g. Docker images, Linux packages)
  • tar.xz for maximum compression ratio (xz compresses better than deflate)
  • You need to preserve Unix permissions, ownership, and extended attributes exactly
  • The archive will be extracted on Unix systems only

When to use ozip

  • You need zip format (cross-platform, Windows compatibility)
  • Speed matters — parallel compression on multi-core servers
  • Backup automation with hooks, email notifications, and error handling
  • Web hosting with low ulimit -u — ozip auto-adjusts
  • You want a single binary with self-update, no package manager needed