When to use what

Need

Use

Interactive shell / scripts

rtrash CLI (or multi-call trash-put etc.)

Safer than permanent delete in Python

rtrash.unlink(path) (after importing rtrash)

Drop-in mental model for rm

rtrash -rf path or symlink rm → put

Permanent purge of trash entries

rtrash empty / rtrash rm PATTERN

Windows / macOS system trash

Not supported (Linux FreeDesktop only)

Safety model and FreeDesktop layout: architecture.org. Measured comparison to Python trash-cli: benchmarks.org. Python API detail: bindings.org.

Install

CLI (Rust)

cargo install --git https://github.com/HaoZeke/rtrash
rtrash setup

rtrash setup installs multi-call links, bash/zsh completions, and the man page under ~/.local from assets embedded in the binary (no source checkout). Flags: --dry-run, --force (after upgrades), --with-rm, --prefix=DIR. Packagers: rtrash completions bash|zsh, rtrash man, or rtrash setup --prefix=/usr.

MSRV 1.77. Default install is a normal dynamically linked Linux binary.

Python (maturin / PyO3)

# from a checkout, on a machine with Rust + maturin:
pip install maturin
maturin develop --features python
# or: pip install .   # uses pyproject.toml / maturin backend
python -c "import rtrash; print(rtrash.version())"

Shortest CLI path

echo data > scratch.txt
rtrash scratch.txt          # put (rm-shaped)
rtrash list
rtrash restore scratch.txt
rtrash scratch.txt
rtrash empty --trash-dir="$XDG_DATA_HOME/Trash"   # pin in scripts/tests

Shortest Python path (replace permanent delete)

import os
from pathlib import Path
import rtrash

# Isolate trash in tests/scripts:
# os.environ["XDG_DATA_HOME"] = "/tmp/my-xdg"

p = Path("scratch.txt")
p.write_text("data")
rtrash.unlink(p)            # was: p.unlink() / os.remove(p)
assert not p.exists()
rtrash.restore_path(p)      # recover
assert p.read_text() == "data"

# directories (was shutil.rmtree):
# rtrash.rmtree("build/")

Next