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

86 lines
3.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# WinDirStat-Export
`wdsexport` scans a directory tree on Linux (or macOS) and writes a
[WinDirStat](https://windirstat.net) 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
```sh
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
```sh
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`](https://github.com/windirstat/windirstat/blob/master/windirstat/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
```sh
python3 -m unittest discover -s tests
python3 tools/gen_langs.py # refresh column names from WinDirStat's language files
```
## License
MIT