Remove empty directories after moving files
This commit is contained in:
+54
-1
@@ -378,6 +378,19 @@ def determine_working_dir(args: list[str]) -> Path:
|
|||||||
return common
|
return common
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup_roots_from_args(args: list[str]) -> list[Path]:
|
||||||
|
roots: list[Path] = []
|
||||||
|
seen: set[Path] = set()
|
||||||
|
for arg in args:
|
||||||
|
path = Path(arg).expanduser()
|
||||||
|
if path.is_dir():
|
||||||
|
resolved = path.resolve()
|
||||||
|
if resolved not in seen:
|
||||||
|
seen.add(resolved)
|
||||||
|
roots.append(resolved)
|
||||||
|
return roots
|
||||||
|
|
||||||
|
|
||||||
def require_exiftool() -> str:
|
def require_exiftool() -> str:
|
||||||
executable = which("exiftool")
|
executable = which("exiftool")
|
||||||
if executable:
|
if executable:
|
||||||
@@ -1151,7 +1164,35 @@ def unique_existing_target(path: Path, planned_sources: set[Path]) -> Path:
|
|||||||
raise RuntimeError(f"Could not find available target name for {path}")
|
raise RuntimeError(f"Could not find available target name for {path}")
|
||||||
|
|
||||||
|
|
||||||
def apply_changes(executable: str, records: list[MediaRecord], choices: UserChoices) -> list[str]:
|
def remove_empty_dirs(cleanup_roots: list[Path], keep_dirs: set[Path]) -> list[Path]:
|
||||||
|
removed: list[Path] = []
|
||||||
|
candidates: set[Path] = set()
|
||||||
|
for root in cleanup_roots:
|
||||||
|
if not root.exists() or not root.is_dir():
|
||||||
|
continue
|
||||||
|
for directory, subdirs, _files in os.walk(root, topdown=False):
|
||||||
|
path = Path(directory).resolve()
|
||||||
|
candidates.add(path)
|
||||||
|
for subdir in subdirs:
|
||||||
|
child = (Path(directory) / subdir).resolve()
|
||||||
|
if child.exists() and child.is_dir():
|
||||||
|
candidates.add(child)
|
||||||
|
|
||||||
|
for directory in sorted(candidates, key=lambda path: len(path.parts), reverse=True):
|
||||||
|
if directory in keep_dirs:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
directory.rmdir()
|
||||||
|
removed.append(directory)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return removed
|
||||||
|
|
||||||
|
|
||||||
|
def apply_changes(
|
||||||
|
executable: str, records: list[MediaRecord], choices: UserChoices
|
||||||
|
) -> list[str]:
|
||||||
failures: list[str] = []
|
failures: list[str] = []
|
||||||
planned_sources = {record.path.resolve() for record in records}
|
planned_sources = {record.path.resolve() for record in records}
|
||||||
|
|
||||||
@@ -1178,6 +1219,14 @@ def apply_changes(executable: str, records: list[MediaRecord], choices: UserChoi
|
|||||||
return failures
|
return failures
|
||||||
|
|
||||||
|
|
||||||
|
def print_removed_dirs(removed_dirs: list[Path]) -> None:
|
||||||
|
if not removed_dirs:
|
||||||
|
return
|
||||||
|
print("\nRemoved empty director" + ("y:" if len(removed_dirs) == 1 else "ies:"))
|
||||||
|
for directory in removed_dirs:
|
||||||
|
print(f" - {directory}")
|
||||||
|
|
||||||
|
|
||||||
def prepare_plan(records: list[MediaRecord], choices: UserChoices) -> list[list[MediaRecord]]:
|
def prepare_plan(records: list[MediaRecord], choices: UserChoices) -> list[list[MediaRecord]]:
|
||||||
apply_time_offset(records, choices.time_offset)
|
apply_time_offset(records, choices.time_offset)
|
||||||
|
|
||||||
@@ -1213,6 +1262,7 @@ def run(argv: list[str]) -> int:
|
|||||||
print(exc)
|
print(exc)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
cleanup_roots = cleanup_roots_from_args(argv[1:])
|
||||||
files = collect_media_files(argv[1:])
|
files = collect_media_files(argv[1:])
|
||||||
if not files:
|
if not files:
|
||||||
print("No supported media files found.")
|
print("No supported media files found.")
|
||||||
@@ -1252,6 +1302,9 @@ def run(argv: list[str]) -> int:
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
failures = apply_changes(exiftool, records, choices)
|
failures = apply_changes(exiftool, records, choices)
|
||||||
|
removed_dirs = remove_empty_dirs(cleanup_roots, keep_dirs={working_dir.resolve()})
|
||||||
|
print_removed_dirs(removed_dirs)
|
||||||
|
|
||||||
if failures:
|
if failures:
|
||||||
print("\nSome files failed:")
|
print("\nSome files failed:")
|
||||||
for failure in failures:
|
for failure in failures:
|
||||||
|
|||||||
Reference in New Issue
Block a user