How to empty folder pruner online for free
- Step 1Open the tool — Visit /archive-tools/empty-folder-pruner. No account is needed for the free tier.
- Step 2Drop a ZIP — Drag your
.zipinto the dropzone or click to browse. The pruner reads ZIP only — for 7z/rar/tar.gz, convert first or use a sibling tool. - Step 3Stay under the free limit — Free allows 50 MB and 500 entries per ZIP. Over either limit you get a tier error before any work runs; upgrade or split the archive.
- Step 4Process — Click Process. The tool parses the central directory, builds the set of referenced directories, decompresses with fflate, and re-zips only the kept entries.
- Step 5Read the metrics — The result panel shows 'Empty dirs removed' and the final 'Entries' count, plus original vs output size — confirm the removed count matches your expectation.
- Step 6Download — Click Download to save
<name>-pruned.ziplocally. Open it to verify the dead folders are gone and every file is intact.
What the pruner keeps vs removes
Decision logic from pruneEmptyFolders in lib/archive/archive-processor.ts. A directory record is any central-directory entry whose name ends in '/'. A directory is 'referenced' if any file entry's path has it as a parent segment.
| Entry in the input ZIP | Pruner decision | Why |
|---|---|---|
A file entry (docs/readme.md) | Kept | Every non-directory entry is preserved byte-for-byte in the output. |
A directory entry that contains a file (docs/) | Kept | Its path is a parent of at least one file, so it is in the 'referenced dirs' set. |
A directory entry with no files under it (logs/) | Removed | No file entry references it as a parent — counted in the 'Empty dirs removed' metric. |
A directory record whose subtree is implied by files (a/b/c.txt but no a/ record) | No change needed | Missing parent records are not invented; the tool only removes records, it never adds them. |
A .DS_Store, ._file, or __MACOSX/ FILE entry | Kept | These are files, not empty directories — use Filename Sanitiser to strip them. |
Tier limits that apply to the Empty Folder Pruner
Limits are enforced per input file before pruning begins (lib/tier-limits.ts, archive family). The pruner reads ONE ZIP at a time on every tier — it is not a batch tool, so the batch-files column only matters for sibling tools that accept folders. entryLimit counts every entry in the ZIP central directory, including the empty directory records you are trying to remove.
| Tier | Max ZIP size | Max entries per ZIP | Files per run |
|---|---|---|---|
| Free | 50 MB | 500 entries | 1 |
| Pro | 500 MB | 50,000 entries | 20 (other tools) |
| Pro + Media | 2 GB | 500,000 entries | 100 (other tools) |
| Developer | 2 GB | 500,000 entries | unlimited (other tools) |
| Enterprise | unlimited | unlimited | unlimited |
Cookbook
Real before/after listings from typical ZIPs that carry empty directory records. Paths are illustrative; the decisions match the actual pruneEmptyFolders logic.
macOS Finder ZIP with dead folders
Compressing a folder in Finder records every subfolder it walks, including empty ones. The pruner keeps Project/src/ (has a file) and removes Project/logs/ and Project/tmp/ (no files).
Input listing (Finder-made release.zip): Project/ Project/src/ Project/src/app.js Project/logs/ Project/tmp/ Output listing (release-pruned.zip): Project/ Project/src/ Project/src/app.js Metrics: Empty dirs removed = 2, Entries = 3
Deeply nested empty tree
An empty nested path like cache/v1/tiles/ produces three directory records, none referenced by a file. All three are removed in one pass.
Input: data/report.csv cache/ cache/v1/ cache/v1/tiles/ Output: data/report.csv Metrics: Empty dirs removed = 3, Entries = 1
Folder that becomes empty after a build prune
If your build emitted a docs/ record but the doc file was excluded, the record is now dead weight. The pruner removes it because no file references docs/.
Input: dist/index.html dist/bundle.js docs/ Output: dist/index.html dist/bundle.js dist/ (kept: parent of two files) Metrics: Empty dirs removed = 1, Entries = 2
Nothing to prune (no-op)
A ZIP where every directory record has files under it is returned unchanged in structure — the tool still re-zips, so timestamps reset, but no entries are dropped.
Input: src/main.py src/util.py src/ Output: src/main.py src/util.py src/ Metrics: Empty dirs removed = 0, Entries = 3
Implicit directories without records
Many ZIPs store a/b/c.txt with no standalone a/ or a/b/ record. There is nothing to prune and nothing to add — the file path already implies the tree on extraction.
Input (no directory records at all): a/b/c.txt readme.md Output (identical structure): a/b/c.txt readme.md Metrics: Empty dirs removed = 0, Entries = 2
Edge cases and what actually happens
Input is not a ZIP (7z/rar/tar.gz renamed to .zip)
RejectedThe pruner parses the ZIP central directory; if no End-Of-Central-Directory record is found it throws 'Not a valid ZIP archive.' Confirm the true format with Auto Format Detector. This tool reads ZIP only — it cannot prune 7z, rar, or tar.gz.
ZIP larger than your tier cap
Tier limit exceededFree is 50 MB, Pro 500 MB, Pro+Media and Developer 2 GB. The size check runs before pruning, so an oversize file fails instantly. Upgrade or split the archive with Archive Splitter.
ZIP has more than your tier's entry limit
Tier limit exceededFree allows 500 entries, Pro 50,000, higher tiers 500,000. The empty directory records you want to remove still count toward this limit, so a folder-heavy ZIP can trip it even when small in bytes.
Timestamps change after pruning
ExpectedThe output is re-zipped with fflate, which writes the current time to every entry because no per-file mtime is supplied. If you need stable dates for reproducible builds, run the result through Timestamp Normaliser.
ZIP is encrypted (password-protected)
Not supportedThe pruner uses fflate's unzipSync, which cannot read AES or ZipCrypto entries. An encrypted ZIP will fail to decompress. Decrypt first, prune, then re-encrypt if needed.
You actually wanted to keep an empty folder
By designAn empty incoming/ or logs/ that a script writes to later is meaningful, and the pruner will remove it because no file references it. If that matters, don't run the tool on that archive.
ZIP contains only directory records and no files
RemovedWith zero file entries there are no referenced directories, so every directory record is empty by definition and all are removed — the output is an empty ZIP. The 'Entries' metric will be 0.
Output looks the same size as the input
ExpectedEmpty directory records are tiny (a few dozen bytes each), so removing them barely changes the byte size. The win is a cleaner listing, not compression — check the 'Empty dirs removed' count to confirm work happened.
Corrupt central directory
RejectedIf the central directory is truncated or damaged, parsing returns no entries and the tool throws 'Not a valid ZIP archive.' Try Corrupted ZIP Repair to salvage what is readable, then prune the repaired file.
Frequently asked questions
Does the Empty Folder Pruner upload my ZIP?
No. Parsing, pruning, and re-zipping all run in your browser tab via fflate. Open DevTools then the Network tab during processing — you will see zero outbound requests carrying your file.
What counts as an empty folder?
A directory record (an entry whose name ends in '/') that no file entry references as a parent. If at least one file lives directly or indirectly under that path, the directory is kept.
Will it delete any of my files?
No. Every non-directory entry is preserved byte-for-byte. The tool only ever removes directory records, never file entries.
What's the maximum size and entry count on the free tier?
Free allows 50 MB and up to 500 entries per ZIP. Pro raises this to 500 MB / 50,000 entries, and Pro+Media and Developer to 2 GB / 500,000 entries. The empty directory records count toward the entry limit.
Can it prune 7z, RAR, or tar.gz?
No. The pruner reads ZIP only. For other formats, convert to ZIP first with Archive Format Converter, or use the matching extractor. Non-ZIP input is rejected with 'Not a valid ZIP archive.'
Why didn't the file get much smaller?
Empty directory records are only a few dozen bytes each, so byte savings are tiny. The benefit is a clean listing without phantom folders — measured by the 'Empty dirs removed' count, not by size.
What does the output file look like?
A standard ZIP named <name>-pruned.zip, recompressed at fflate level 6. It opens in Explorer, Finder, unzip, 7-Zip, or any consumer — there is no JAD-specific format.
Does it remove .DS_Store or __MACOSX files?
No — those are files, not empty directories, so the pruner keeps them. To strip macOS cruft, use Filename Sanitiser.
Are there any options to configure?
No. The pruner has a single, deterministic behaviour and no settings — drop a ZIP, click Process, download. There is no report-only mode in the current build.
Will my folder timestamps survive?
No. Re-zipping with fflate stamps every entry with the current time. For reproducible dates, pipe the result through Timestamp Normaliser.
Which browsers work?
Any modern browser with WebAssembly: Chrome, Edge, Firefox, Safari, Brave, Opera, including mobile. Very large archives may exceed device memory on phones because everything is held in RAM.
Is there an API or CLI?
Not currently — the tool is a browser page only (execution is browser-only by design). The closest local equivalent is fflate in Node, which is exactly what this tool wraps.
Privacy first
Every JAD Archive tool runs entirely in your browser using fflate, @zip.js/zip.js, and the libarchive WASM bridge. Your archives never leave your device — verified by zero outbound network requests during processing.