A fast, modern folder size analyzer for Windows. See what's eating your disk — as a tree, a treemap, a top-files list, a file-type breakdown, or duplicate copies.
Grab the latest build from the Releases page:
FolderLens.exe— standalone, no Python required. Just run it.FolderLens-<version>-win64.zip— folder build; use this if your antivirus flags the single exe (see Antivirus notes).FolderLens_Setup_<version>.exe— versioned installer with Start Menu and optional Explorer context-menu integration.
Opens on a start screen offering Home, Desktop, Downloads, Documents, Pictures, Videos, Music and your drives — pick one and it scans, no file dialog required.
FolderLens scans a whole directory tree once — with a shared work queue and a bounded worker pool that keeps one large folder parallel, avoids creating one task per subtree, and automatically uses gentler metadata concurrency for UNC and mapped network drives. The complete in-memory tree can then be explored six different ways with zero rescanning:
- 🧭 Explore — keep the folder hierarchy, treemap, and selection details visible together. Selecting a row or map tile follows the same item on the other side; zooming the map keeps the tree open.
- 🌳 Tree view — expandable folder tree with a usage bar, size, item count, type, and date at every level. Expanding a folder is instant.
- 🗺️ Treemap — a hierarchy-first cushion-shaded map where every rectangle's area is its size, folders get a reserved header band, labels are capped to the useful large tiles, and dense tails are grouped into a single “smaller items” tile. Image files are painted with their own thumbnail so you can recognise them at a glance. Hover for a peek preview of the picture, click a folder to zoom in, right-click to go back.
- 🏆 Largest files — the top 100 biggest files anywhere in the tree, with their locations and small inline previews.
- 🧩 File types — size and count broken down by category (video, image, code, …) with proportional bars.
- 🎛️ Type and advanced filters — apply categories, extensions, filename terms, size and modified-date ranges, and hidden-file rules across every view. Matching folders remain as context, and Windows hidden attributes are respected.
- 👯 Duplicates — finds byte-identical copies and shows exactly how much space keeping one of each would free. Narrowed by size, then a head/tail sample, then a full hash, so almost nothing is read twice.
- ⭐ Filter presets — one-click presets such as Images only, Large videos, and Not modified for a year, plus your own saved filters.
- 🕰️ File age — the File Types view also groups the same files by last-modified age.
- 💾 On-disk size (opt-in) — for local drives, measure allocated and unique on-disk bytes and hardlinks next to the logical size. Unknown values stay “unknown”; nothing is estimated.
- ⏭️ Skip a stuck folder — when a network folder stops responding, skip it and let the scan finish; the result is clearly marked partial.
Double-click any image (in any view) to open it:
- ◀ ▶ step through every image in the folder, with a position counter
- ⬅ Up and a subfolder picker to move around without leaving the viewer
- ✏️ Annotate in two modes:
- Basic — pen, marker, arrow, eraser
- Advanced — adds line, rectangle, ellipse, text, and redo
- colour palette, brush size, undo/redo, clear, and Save as… to export the annotated copy at full resolution
Annotations are stored relative to the image, so they stay put when you resize or zoom, and export sharp at the original resolution.
Plus:
- 🧭 Clickable breadcrumbs — jump straight to any folder in the path
- 🎨 Colour legend under the treemap, so the colours actually mean something
- ⌨️ Keyboard treemap navigation — arrow keys move through tiles, Enter opens the focused item, and Backspace goes up. In Explore, the focused item also selects its row in the folder tree.
- ⌨️ Shortcut help built in (F1), and hover hints on every icon button
- 🔎 Instant search across the whole tree (Ctrl+F)
- 🧵 Fully responsive — scanning, zipping, deleting, and exporting all run off the UI thread, with live progress and a Stop button
- 🗑️ Manage — multi-select to zip, delete, or open in Explorer (right-click, toolbar, or Delete key); sizes update without rescanning
- 📤 Export the current visible results or full scan as a scoped CSV or JSON report, or the treemap as a PNG
- ♻️ Recycle Bin — deletions are undoable by default (permanent delete is a setting)
- 💽 Disk usage shown in the status bar (free / total)
- 🌗 Light / dark theme, remembered between sessions, along with your last folder and view
- ⬆️ Auto-update from GitHub releases
- 🖱️ Explorer context menu integration
- 🛡️ Handles "access denied" gracefully and flags how many items it couldn't read
# open the app
python main.py
# analyze a specific folder
python main.py "C:\Users\Documents"
# console mode (no gui)
python main.py --console "C:\Users\Documents"
# Explorer context menu (run as admin)
python main.py --install
python main.py --uninstall
# print version
python main.py --version
# headless reports: same scanner, filters, and export format as the app
python main.py "D:\Photos" --category image --json photos.json
python main.py "D:\Work" --ext .log --modified-before 2025-01-01 --csv old-logs.csv
python main.py "C:\Data" --on-disk --consoleReport mode never deletes, moves, or zips anything. It exits with 0 for a
complete scan, 2 when some folders could not be read (partial totals), and
1 on failure. Any filter option (--category, --ext, --name,
--min-mib, --max-mib, --modified-after, --modified-before,
--exclude-hidden, --on-disk) runs headless.
| Key | Action |
|---|---|
F5 |
Rescan current folder |
Ctrl+F |
Focus search |
Esc |
Clear search |
Delete |
Delete selected (tree / largest files / duplicates) |
F1 |
Keyboard shortcut help |
Ctrl+O |
Browse for a folder |
Backspace |
Go to the parent folder |
| Double-click | Open folder / open image viewer |
In the image viewer:
| Key | Action |
|---|---|
← → |
Previous / next image |
Ctrl+Z / Ctrl+Y |
Undo / redo annotation |
Esc |
Close |
In the Treemap, Tab to the map, use the arrow keys to focus a tile, press Enter to zoom into a folder or open an image, press Backspace to move up, and press Shift+Backspace to move forward in the zoom history. The Tree view provides the full hierarchy as a keyboard accessible table.
- Windows 10/11
- Python 3.9+ (only when running from source)
PyInstaller executables are commonly false-flagged by antivirus engines. The
build is tuned to minimize this (no UPX, embedded metadata, manifest, icon, and
a folder-build alternative). If your machine still quarantines the download,
see docs/ANTIVIRUS.md — the short version is: use the
.zip folder build, and/or report the false positive to Microsoft (they delist
confirmed ones quickly).
pip install -r requirements.txt pytest
# run the test suite
python -m pytest tests -v
# build both executables locally (Windows)
build.bat
# build the versioned installer (Windows, Inno Setup 6 required)
python installer/build_installer.pyCreate each corpus once. The generator writes deterministic, nested .bin
files and refuses to populate a nonempty directory:
python benchmarks/create_dataset.py C:/test-data/files-10k --files 10000
python benchmarks/create_dataset.py C:/test-data/files-100k --files 100000
python benchmarks/create_dataset.py C:/test-data/files-1m --files 1000000For a share run, copy the corpus to the share first and scan that unchanged copy. Run the same harness against the same unchanged folder or share for each version, and keep the report files outside the scanned folder:
$harness = 'C:/work/FolderLens/benchmarks/scan_baseline.py'
$env:FOLDERLENS_SCANNER_SOURCE = 'C:/work/FolderLens-v3.4.0'
python $harness C:/test-data/million-files --runs 5 --version-label v3.4.0 `
--dataset-label local-1m --storage-label NVMe-SSD --cache-state warm `
--defender enabled --output C:/bench/3.4.0.json
Remove-Item Env:FOLDERLENS_SCANNER_SOURCE
python $harness C:/test-data/million-files --runs 5 --version-label 4.0-candidate `
--dataset-label local-1m --storage-label NVMe-SSD --cache-state warm `
--defender enabled --output C:/bench/candidate.json
python C:/work/FolderLens/benchmarks/compare_scans.py C:/bench/3.4.0.json `
C:/bench/candidate.json --output C:/bench/comparison.jsonFor the shipped v3.4.0 baseline, point FOLDERLENS_SCANNER_SOURCE at a clean
v3.4.0 checkout. The current harness adapts to its older scanner callback API;
--version-label records the tag while application_version preserves the
version embedded in that source. Use matching dataset labels, cache state,
Defender state, host, and path. The report includes first
progress, time to the first visible file sample, first 500 entries, first
partial result, scan duration, process RSS, Python allocation peak, queue
high-water marks, item count, and inaccessible paths. During a scan the app
shows a provisional list of up to 25 largest files seen so far; it is clearly
labeled until the final ranking is available. For SMB runs, pass the measured --network-rtt-ms and
--network-bandwidth-mbps. Timeout runs cancel and are marked incomplete. The
comparison reports ratios and checks whether both versions scanned the same
item and inaccessible counts; it does not treat a single run as a release
verdict.
Snapshot bytes are observed values until the scan finishes; inaccessible paths keep a completed result partial. Logical size counts each hardlink path separately. Reparse points and symlinks are listed but never traversed by default. This harness measures scanning; record SMB RTT/bandwidth and UI input latency separately, and repeat both warm-cache and cold-cache runs.
FolderLens/
├── main.py # entry point and command-line options
├── cli.py # headless JSON/CSV reports and exit codes
├── query.py # shared QuerySpec projection engine and filter presets
├── app.py # UI (customtkinter + ttk): views, image viewer, toolbars
├── scanner.py # single-pass parallel tree scanner
├── analysis.py # query projections, treemap layout, largest-files, CSV
├── file_actions.py # stale-scan validation and safe ZIP/delete operations
├── duplicates.py # size -> sample -> full hash duplicate detection (pure, tested)
├── locations.py # start-screen places and path breadcrumbs (pure, tested)
├── trash.py # Recycle Bin / XDG trash, with a permanent-delete fallback
├── treemap_render.py # cushion shading, thumbnails, labels, hit-testing
├── thumbnails.py # background thumbnail decoding + LRU cache
├── annotate.py # annotation model, tools, undo/redo, export (pure, tested)
├── imagenav.py # image/folder navigation for the viewer (pure, tested)
├── file_utils.py # file type detection, formatting
├── updater.py # auto-update handler
├── version.py # version info
├── registry_installer.py # Windows Explorer context menu
├── release_manifest.py # SHA-256 manifest for release assets
├── benchmarks/ # dataset generator, scan harness, report comparison
├── FolderLens.spec # antivirus-friendly PyInstaller build
├── app.manifest # asInvoker + DPI + supported-OS manifest
├── make_version_info.py # generates the embedded Windows version resource
├── installer/ # versioned Inno Setup installer and build script
├── assets/ # app icon (+ generator)
├── tests/ # pytest suite
├── docs/ # antivirus notes and the 4.0 acceptance checklist
├── CHANGELOG.md # release notes
└── .github/workflows/ # CI (tests) + Release (exe, folder zip, installer)
Push a tag like v4.0.0 (or run the Release workflow with a tag input).
It runs the tests, generates the version resource, builds the AV-friendly
one-file exe, one-directory zip, and versioned installer on Windows, smoke-tests
the executable and installer install/uninstall flow, and publishes a GitHub
release with all three assets and their SHA-256 manifest. The in-app updater
uses the one-file exe or folder zip; installer builds are for fresh installs.
MIT