Files
Lucas WintherandClaude Opus 5.5 e28fbeb0b3 Add wdsexport: Linux directory scan to WinDirStat 2.x saved-results CSV
Single-file, stdlib-only CLI that writes the CSV format WinDirStat's
CsvLoader accepts (parent-before-child rows, subtree totals, localized
headers for all 25 UI languages). Includes install.sh, pyproject entry
point, unit tests and a generator for the language table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 22:01:02 +01:00

3.3 KiB
Raw Permalink Blame History

WinDirStat-Export

wdsexport scans a directory tree on Linux (or macOS) and writes a WinDirStat 2.x saved-results CSV. Copy it to a Windows machine and open it with File → Open saved results to browse the remote disk with WinDirStat's treemap.

Single Python file, standard library only, Python 3.8+.

Install

git clone https://gitea.lucaswinther.info/lucasw89/WinDirStat-Export.git
cd WinDirStat-Export
./install.sh                # -> ~/.local/bin/wdsexport
# or: ./install.sh /usr/local   (with sudo)
# or: pipx install .

Usage

wdsexport                          # scan /, write ./<hostname>-root.csv
wdsexport / --zip                  # also write a .zip (CSVs compress ~15x)
sudo wdsexport /                   # include root-only dirs (/var/lib/docker, ...)
wdsexport ~/projects -o proj.csv   # scan one directory
wdsexport / --exclude /home/me/vms --lang da
wdsexport / -o - | gzip > scan.csv.gz
Argument Default Meaning
PATH / Directory to scan
-o, --output FILE ./<name>.csv Output CSV; - writes to stdout
--name NAME <hostname>-<dirname> Root folder name shown in WinDirStat
--exclude DIR — Skip a directory (repeatable)
--zip off Also write <output>.zip
--lang CODE en Column-name language (see below)
--cross-fs off Descend into other mounted filesystems (default stays on one, like du -x)
-q, --quiet off No progress output

--lang must match WinDirStat's UI language

WinDirStat identifies CSV columns by their localized header names. If your WinDirStat runs in Danish, export with --lang da; otherwise the file is rejected. Supported: ar, cs, da, de, en, es, et, fi, fr, hi, hu, it, ja, ko, nb, nl, pl, pt, ru, sl, sv, tr, uk, zh, zh-HK.

What gets recorded

  • Logical size = file length; physical size = allocated blocks (st_blocks × 512), so sparse files and filesystem overhead show correctly.
  • Hard-linked files are counted once (first path seen).
  • Symlinks are recorded as small files and never followed.
  • Dotfiles get the Hidden attribute, so enable show hidden files in WinDirStat.
  • Directories that can't be read are marked partial (WinDirStat shows them as incomplete). Run with sudo to include them.
  • Characters WinDirStat's CSV parser can't handle in names are replaced: \ → _, " → ', newlines → space. Invalid UTF-8 becomes �.
  • The tool skips its own output and temporary files when they sit inside the scanned tree.

Disk space: the scan writes a temporary file about the size of the final CSV next to the output (in $TMPDIR for -o -). Roughly 200 bytes per file, so 8 million files ≈ 1.5 GB CSV, ≈ 100 MB zipped.

How it works

The format follows WinDirStat's own loader (CsvLoader.cpp): rows must list each parent before its children, paths use \ separators, and folder rows carry subtree totals. wdsexport writes rows in post-order (when folder totals are known) to a temp file and then copies it out reversed, which gives a parent-first order without holding the tree in memory.

Development

python3 -m unittest discover -s tests
python3 tools/gen_langs.py       # refresh column names from WinDirStat's language files

License

MIT