rusty-detox
Sanitize messy filenames. A Rust port of Doug Harple's detox(1) with the full upstream filter pipeline, detoxrc config grammar, recursive collision-safe batch rename, EXDEV cross-device fallback, and a typed library API.
Part of the Rusty portfolio.
Install
# or, with prebuilt binaries:
Usage
# Preview a rename (dry-run)
# My Résumé (final v2).pdf -> My_Resume_final_v2.pdf
# Recursive batch-rename a directory tree
# Pick a sequence
# List loaded sequences
Cargo Features
| Feature | Default | What it gates |
|---|---|---|
cli |
yes | clap + clap_complete + anyhow + terminal_size + walkdir |
inline-detox |
no | Upstream-canonical inline-detox companion binary |
Library consumers can use rusty-detox = { version = "0.1", default-features = false } to get the filter pipeline + library API without any CLI dependencies.
Library API
use ;
let detox = new
.sequence
.build;
let cleaned = detox.sanitize;
// cleaned == "My_Resume_final_v2.pdf"
Compatibility
rusty-detox has two modes:
- Default — clap-styled flag parser; rejects conflicting flag pairs at parse time; adds
--help,--version,completionssubcommand. - Strict (
--strict, envRUSTY_DETOX_STRICT=1, or argv[0] =detox/detox-alias) — byte-equal stderr against upstream v3.0.1 for documented diagnostics; last-wins flag resolution; no subcommands.
The upstream Table.utf_8 and Table.iso8859_1 are vendored at v3.0.1 freeze; future re-vendoring is a MAJOR semver bump.
Concurrency
The EXDEV cross-device rename fallback (copy + fsync + rename + unlink) is not atomic across the full chain — a concurrent reader could observe both the source and target briefly. Upstream detox(1) has the same property. Run rusty-detox to completion on a quiescent tree if external observers are critical.
MSRV
Rust 1.85 (edition 2024). Re-verified against stable-minus-two policy at each release.
License
Dual-licensed under MIT or Apache-2.0.