feat(rename-children): add optional flatten mode
This commit is contained in:
+34
-22
@@ -5,36 +5,48 @@ import dataclasses
|
|||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
|
||||||
import re
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
def parse_args():
|
def parse_args():
|
||||||
arger = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
arger = argparse.ArgumentParser(
|
||||||
arger.add_argument('dirs', help='Path to the directories', type=Path, nargs='+')
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter
|
||||||
|
)
|
||||||
|
arger.add_argument("dirs", help="Path to the directories", type=Path, nargs="+")
|
||||||
|
arger.add_argument(
|
||||||
|
"--flatten", help="Flatten directory structure", action="store_true"
|
||||||
|
)
|
||||||
return arger.parse_args()
|
return arger.parse_args()
|
||||||
|
|
||||||
|
|
||||||
def natural_sort_key(path: Path) -> tuple[str, ...]:
|
def rename_children(source_dir: Path, flatten: bool) -> None:
|
||||||
|
def natural_sort_key(path: Path) -> tuple[str, ...]:
|
||||||
s = path.stem
|
s = path.stem
|
||||||
return tuple(f'{int(p):010d}' if p.isnumeric() else p for p in re.findall(r'(\D+|\d+)', s))
|
return tuple(
|
||||||
|
f"{int(p):010d}" if p.isnumeric() else p
|
||||||
|
for p in re.findall(r"(\D+|\d+)", s)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert source_dir.is_dir()
|
||||||
|
|
||||||
def rename_children(cwd: Path) -> None:
|
if flatten:
|
||||||
assert cwd.is_dir()
|
files = [f for f in source_dir.rglob("*") if f.is_file()]
|
||||||
|
else:
|
||||||
|
files = [f for f in source_dir.iterdir() if f.is_file()]
|
||||||
|
|
||||||
files = [f for f in cwd.glob('*') if f.is_file()]
|
|
||||||
files = sorted(files, key=natural_sort_key)
|
files = sorted(files, key=natural_sort_key)
|
||||||
|
|
||||||
new_stem = cwd.name
|
|
||||||
|
|
||||||
jobs = []
|
jobs = []
|
||||||
for i, f in enumerate(files):
|
for i, f in enumerate(files):
|
||||||
target = f.with_stem(f'{new_stem}__{i:04d}')
|
ext = ".jpg" if f.suffix.lower() in {".jpeg", ".jpg"} else f.suffix
|
||||||
if f.suffix == '.jpeg':
|
target_dir = f.parent
|
||||||
target = target.with_suffix('.jpg')
|
if flatten:
|
||||||
|
target_dir = source_dir
|
||||||
|
new_stem = source_dir.name
|
||||||
|
target = target_dir / f"{new_stem}__{i:04d}{ext}"
|
||||||
if target.is_file():
|
if target.is_file():
|
||||||
logging.error(f'target already exists: {target}')
|
logging.error(f"target already exists: {target}")
|
||||||
continue
|
continue
|
||||||
jobs.append(MoveOp(source=f, target=target))
|
jobs.append(MoveOp(source=f, target=target))
|
||||||
f.rename(target)
|
f.rename(target)
|
||||||
@@ -52,24 +64,24 @@ class MoveOp:
|
|||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
return {
|
return {
|
||||||
'source': str(self.source),
|
"source": str(self.source),
|
||||||
'target': str(self.target),
|
"target": str(self.target),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def write_undo_script(save_dir: Path, ops: list[MoveOp]):
|
def write_undo_script(save_dir: Path, ops: list[MoveOp]):
|
||||||
now = datetime.datetime.now().isoformat().replace(':', '')
|
now = datetime.datetime.now().isoformat().replace(":", "")
|
||||||
save_path = save_dir / f'undo_{now}.json'
|
save_path = save_dir / f"undo_{now}.json"
|
||||||
with save_path.open('w', encoding='utf-8') as f:
|
with save_path.open("w", encoding="utf-8") as f:
|
||||||
for it in ops:
|
for it in ops:
|
||||||
f.write(json.dumps(it.to_dict()) + '\n')
|
f.write(json.dumps(it.to_dict()) + "\n")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
args = parse_args()
|
args = parse_args()
|
||||||
for d in args.dirs:
|
for d in args.dirs:
|
||||||
rename_children(d)
|
rename_children(source_dir=d, flatten=args.flatten)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user