Normalize timestamp group folder names
This commit is contained in:
+14
-2
@@ -12,11 +12,23 @@ Files are sorted by their current path and moved into one folder named
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ORDERED_TIMESTAMP_STEM_RE = re.compile(r"^(?P<timestamp>\d{8}_\d{6})-[1-9]\d*$")
|
||||
|
||||
|
||||
def group_stem(path: Path) -> str:
|
||||
stem = path.stem
|
||||
match = ORDERED_TIMESTAMP_STEM_RE.match(stem)
|
||||
if match:
|
||||
return match.group("timestamp")
|
||||
return stem
|
||||
|
||||
|
||||
def unique_path(path: Path) -> Path:
|
||||
if not path.exists():
|
||||
return path
|
||||
@@ -87,8 +99,8 @@ def group_items(items: list[Path]) -> Path | None:
|
||||
return None
|
||||
|
||||
sorted_items = sorted(items, key=lambda item: item.name.lower())
|
||||
first = sorted_items[0].stem
|
||||
last = sorted_items[-1].stem
|
||||
first = group_stem(sorted_items[0])
|
||||
last = group_stem(sorted_items[-1])
|
||||
target_dir = unique_path(working_dir_for_items(sorted_items) / f"{first}-{last}")
|
||||
target_dir.mkdir(parents=True)
|
||||
|
||||
|
||||
+29
-5
@@ -84,6 +84,7 @@ TIME_ONLY_RE = re.compile(
|
||||
TZ_RE = re.compile(r"^(?P<sign>[+-])(?P<h>\d{1,2})(?::?(?P<m>\d{2}))?$")
|
||||
OFFSET_RE = re.compile(r"^([+-])(?:(\d+):)?(\d{1,2})(?::(\d{2}))?$")
|
||||
TOKEN_SHIFT_RE = re.compile(r"(\d+|[a-zA-Z]+)")
|
||||
ORDERED_TIMESTAMP_STEM_RE = re.compile(r"^(?P<timestamp>\d{8}_\d{6})-[1-9]\d*$")
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -917,6 +918,14 @@ def normalized_extension(path: Path) -> str:
|
||||
return path.suffix.lower()
|
||||
|
||||
|
||||
def group_stem_from_name(name: str) -> str:
|
||||
stem = Path(name).stem
|
||||
match = ORDERED_TIMESTAMP_STEM_RE.match(stem)
|
||||
if match:
|
||||
return match.group("timestamp")
|
||||
return stem
|
||||
|
||||
|
||||
def plan_names(records: list[MediaRecord], choices: UserChoices) -> None:
|
||||
if not choices.rename_files:
|
||||
for record in records:
|
||||
@@ -981,12 +990,27 @@ def assign_groups(records: list[MediaRecord], groups: list[list[MediaRecord]]) -
|
||||
record.group_id = index
|
||||
|
||||
|
||||
def assign_group_names(groups: list[list[MediaRecord]]) -> None:
|
||||
def unique_group_name(base_name: str, working_dir: Path, used_names: set[str]) -> str:
|
||||
if base_name not in used_names and not (working_dir / base_name).exists():
|
||||
used_names.add(base_name)
|
||||
return base_name
|
||||
|
||||
for index in range(1, 10000):
|
||||
candidate = f"{base_name}-{index}"
|
||||
if candidate not in used_names and not (working_dir / candidate).exists():
|
||||
used_names.add(candidate)
|
||||
return candidate
|
||||
|
||||
raise RuntimeError(f"Could not find an available group directory name for {base_name}")
|
||||
|
||||
|
||||
def assign_group_names(groups: list[list[MediaRecord]], working_dir: Path) -> None:
|
||||
used_names: set[str] = set()
|
||||
for group in groups:
|
||||
ordered = sorted(group, key=photo_sort_key)
|
||||
first = Path(ordered[0].final_name or ordered[0].path.name).stem
|
||||
last = Path(ordered[-1].final_name or ordered[-1].path.name).stem
|
||||
group_name = f"{first}-{last}"
|
||||
first = group_stem_from_name(ordered[0].final_name or ordered[0].path.name)
|
||||
last = group_stem_from_name(ordered[-1].final_name or ordered[-1].path.name)
|
||||
group_name = unique_group_name(f"{first}-{last}", working_dir, used_names)
|
||||
for record in ordered:
|
||||
record.group_name = group_name
|
||||
|
||||
@@ -1165,7 +1189,7 @@ def prepare_plan(records: list[MediaRecord], choices: UserChoices) -> list[list[
|
||||
|
||||
plan_names(records, choices)
|
||||
if groups:
|
||||
assign_group_names(groups)
|
||||
assign_group_names(groups, choices.working_dir)
|
||||
plan_targets(records, choices)
|
||||
return groups
|
||||
|
||||
|
||||
Reference in New Issue
Block a user