What rtrash is¶
A native FreeDesktop trash implementation: one Rust library driving
the rtrash multi-call CLI and optional Python bindings. Files are
moved into the same trash layout used by GNOME/KDE/Xfce file
managers, not unlinked.
FreeDesktop layout¶
Location |
Role |
|---|---|
|
Home trash (default
|
|
Per-mount shared trash (sticky, non-symlink) |
|
Per-mount private trash |
|
Payload + |
Atomic reservation: create-new on .trashinfo before moving the
payload (spec requirement). Collisions become name.2, name.3, …
Safer than permanent delete (os.remove / rm without trash)¶
Risk |
|
rtrash put |
|---|---|---|
Data gone immediately |
Yes |
No — recoverable until empty |
Shared with DE trash UI |
No |
Yes (FreeDesktop) |
Accidental
|
Permanent |
Recover with
|
Cross-device |
Unlink only |
Copy-into-home-trash fallback |
rtrash put also applies rm-shaped fail-safes: refuse . / ..
/ / (with preserve-root), require -r for directories, GNU-style
last-wins for -f / -i / -I, exit codes 0/1/2.
Safer than a naive “mv to ~/. Trash” script¶
Correct
.trashinfoencoding (percent-encodedPath)Mount-aware placement (not only home trash)
Concurrent-safe name allocation
Restore overwrite protection (
-fto replace)Empty with age filter, dry-run, orphan purge,
directorysizesprune
Versus Python trash-cli (design, not speed)¶
Axis |
trash-cli |
rtrash |
|---|---|---|
Runtime |
CPython suite of scripts |
Single native binary / lib |
FreeDesktop put/l ist/empty/restore/rm |
Yes |
Yes (multi-call + subcommands) |
rm-compatible put flags |
Partial (own CLI) |
Strong (GNU-style set) |
Permanent
|
Separate process spawn |
In-process Python module |
Parallel full empty |
Sequential Python |
Rayon + bulk unlinkat; btrfs subvol ioctl when applicable |
Where permanent delete is still preferable¶
You intend unrecoverable wipe (secrets, free space forensics)
Non-Linux platforms (use OS trash APIs, not this crate)
You must delete inside the trash by policy that forbids recoverability
Use rtrash empty / trash-rm only after accepting permanent loss
of those entries.
Durability and multi-volume (shipped)¶
Put fsyncs the reserved
.trashinfobefore the payload move.Cross-device (EXDEV) put/restore preserve content, symlink targets, mode, and mtime.
Each trash root uses an exclusive
flockon.rtrash.lockfor put and empty.Volume topdir is the longest matching mount point from
/proc/self/mounts(btrfs multi-subvol safe; not purest_devparent walk alone).Default empty/list/restore/rm scan home trash plus existing trash on every non-pseudo mount (trash-cli multi-volume parity), including
/.
Library layout¶
src/lib.rs public modules + optional python feature
src/main.rs multi-call CLI dispatcher
src/put.rs rm-compatible trash put
src/empty.rs age filter + full wipe path
src/fastdelete.rs unlinkat tree walk; btrfs subvol destroy
src/list.rs restore.rs rm.rs trashdir.rs info.rs util.rs
src/python.rs PyO3 (feature = python)
CLI and Python call the same put/empty/list/restore entry points—no second filesystem model.