feat(multi-rename): add safer move and trash flow
This commit is contained in:
Regular → Executable
+20
-11
@@ -1,4 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
from functools import cache
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
@@ -34,20 +36,22 @@ def edit_text(text: str) -> str | None:
|
||||
return temp_file_path.read_text()
|
||||
|
||||
|
||||
def move_to_trash(file_path: Path):
|
||||
def move_to_trash(file_path: Path) -> None:
|
||||
"""Move file to Trash using trash CLI."""
|
||||
if not file_path.is_file():
|
||||
raise FileNotFoundError
|
||||
raise FileNotFoundError(f"File not found: {file_path}")
|
||||
|
||||
subprocess.run(
|
||||
[
|
||||
"osascript",
|
||||
"-e",
|
||||
f'tell app "Finder" to move POSIX file "{file_path}" to trash',
|
||||
],
|
||||
["trash", str(file_path.resolve())],
|
||||
check=True,
|
||||
)
|
||||
|
||||
|
||||
@cache
|
||||
def make_dir(path: Path) -> None:
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
def rename_files(files: list[Path], cwd: Path | None = None):
|
||||
if not cwd:
|
||||
cwd = files[0].parent
|
||||
@@ -58,25 +62,30 @@ def rename_files(files: list[Path], cwd: Path | None = None):
|
||||
return
|
||||
edited = edited_raw.splitlines(keepends=False)
|
||||
|
||||
if len(edited) != len(originals):
|
||||
logging.error("number of edited lines does not match number of original lines")
|
||||
return
|
||||
|
||||
deletables = []
|
||||
moveables = []
|
||||
moveables: list[tuple[Path, Path]] = []
|
||||
for source, target in zip(originals, edited):
|
||||
if target.startswith("#") or target == "":
|
||||
deletables.append(Path(source))
|
||||
deletables.append((cwd / source).resolve())
|
||||
continue
|
||||
if source != target:
|
||||
moveables.append((cwd / source, cwd / target))
|
||||
|
||||
for source, target in moveables:
|
||||
logging.info(f"moving {source} -> {target}")
|
||||
make_dir(target.parent)
|
||||
source.rename(target)
|
||||
|
||||
for f in deletables:
|
||||
try:
|
||||
logging.info(f"trashing {f}")
|
||||
move_to_trash(f)
|
||||
except:
|
||||
logging.error(f"failed to trash {f}")
|
||||
except Exception as e:
|
||||
logging.error(f"failed to trash {f}: {e}")
|
||||
|
||||
|
||||
def parse_args():
|
||||
|
||||
Reference in New Issue
Block a user