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>
86 lines
3.3 KiB
Markdown
86 lines
3.3 KiB
Markdown
# 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
|