4 Commits

Author SHA1 Message Date
Marco D'Aleo
be9867a007 Merge pull request #11 from mdaleo404/resrm_trash_life
Add automatic prune of trash older than $RESRM_TRASH_LIFE
2025-11-12 17:37:52 +00:00
e76c8726a2 Add automatic prune of trash older than RESRM_TRASH_LIFE value, update README, package version bump 2025-11-12 17:36:51 +00:00
657f14d95d Update README 2025-11-11 19:02:30 +00:00
Marco D'Aleo
b6c6fcc14d Merge pull request #10 from mdaleo404/flags_improvement
Flags improvement
2025-11-11 18:54:05 +00:00
3 changed files with 56 additions and 7 deletions

View File

@@ -7,11 +7,23 @@ It moves files to a per-user _trash_ instead of permanently deleting them, while
## Features ## Features
- Move files and directories to a **trash folder** instead of permanent deletion - Move files and directories to a **Trash folder** instead of permanent deletion
- Restore deleted files by **short ID or exact basename** - Restore deleted files by **short ID or exact basename**
- Empty trash safely - Empty trash safely
- Supports `-r`, `-f`, `-i`, `--perma` options - Supports `-r`, `-f`, `-i`, `--skip-trash` options
- Works with `sudo` for root-owned files - Works with `sudo` for root-owned files
- Automatically prunes Trash entries older than `$RESRM_TRASH_LIFE` days (default **7**, minimum **1**)
> Note: if you need immediate deletion, use the regular `rm` command instead.
---
## Configuration
To control how long trashed files are kept, add this line to your shell configuration (e.g. `~/.bashrc`):
```bash
export RESRM_TRASH_LIFE=10
```
--- ---
@@ -57,7 +69,7 @@ resrm -f file
resrm -i file resrm -i file
# Permanent delete (bypass trash) # Permanent delete (bypass trash)
resrm --perma file resrm --skip-trash file
# List trash entries # List trash entries
resrm -l resrm -l

View File

@@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "resrm" name = "resrm"
version = "0.2.1" version = "0.3.0"
description = "drop-in replacement for rm with undo/restore built-in." description = "drop-in replacement for rm with undo/restore built-in."
authors = ["Marco D'Aleo <marco@marcodaleo.com>"] authors = ["Marco D'Aleo <marco@marcodaleo.com>"]
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"

View File

@@ -53,6 +53,42 @@ def get_trash_paths() -> tuple[Path, Path]:
TRASH_DIR, META_FILE = get_trash_paths() TRASH_DIR, META_FILE = get_trash_paths()
DATEFMT = "%Y-%m-%d %H:%M" DATEFMT = "%Y-%m-%d %H:%M"
def prune_old_trash():
"""Remove trash entries older than RESRM_TRASH_LIFE days (default 7)."""
try:
life_days = int(os.environ.get("RESRM_TRASH_LIFE", "7"))
except ValueError:
life_days = 7
if life_days < 1:
life_days = 1
cutoff = datetime.datetime.now() - datetime.timedelta(days=life_days)
removed = 0
for entry in list(meta): # make copy since we'll modify meta
try:
ts = datetime.datetime.fromisoformat(entry["timestamp"])
except Exception:
continue # skip malformed entries
if ts < cutoff:
f = TRASH_DIR / entry["id"]
try:
if f.exists():
if f.is_dir():
shutil.rmtree(f, ignore_errors=True)
else:
f.unlink(missing_ok=True)
meta.remove(entry)
removed += 1
except Exception as e:
print(f"Failed to prune {f}: {e}")
if removed > 0:
save_meta(meta)
print(f"Pruned {removed} trash entr{'y' if removed == 1 else 'ies'} older than {life_days} da{'y' if life_days == 1 else 'ys'}.")
def load_meta() -> List[Dict]: def load_meta() -> List[Dict]:
if META_FILE.exists(): if META_FILE.exists():
try: try:
@@ -304,6 +340,7 @@ def move_to_trash(path: Path, interactive: bool, force: bool, skip_trash: bool):
def main(argv: Optional[List[str]] = None): def main(argv: Optional[List[str]] = None):
if argv is None: if argv is None:
argv = sys.argv[1:] argv = sys.argv[1:]
prune_old_trash()
parser = argparse.ArgumentParser(add_help=False) parser = argparse.ArgumentParser(add_help=False)
parser.add_argument("paths", nargs="*", help="files to remove") parser.add_argument("paths", nargs="*", help="files to remove")
parser.add_argument("-r", action="store_true", help="recursive") parser.add_argument("-r", action="store_true", help="recursive")