133 lines
4.6 KiB
Python
133 lines
4.6 KiB
Python
#!python
|
|
|
|
# https://github.com/hMatoba/Piexif
|
|
# http://ce3wiki.theturninggate.net/doku.php?id=file_name_convention
|
|
# destination: <BASE>/<year>/<YYYYMMDD> <Event>/ab-<YYYYMMDD>-<Event>-<nnnn>.jpg
|
|
|
|
from pathlib import Path
|
|
import datetime as dt
|
|
import piexif
|
|
from collections import defaultdict
|
|
import re
|
|
|
|
SRC = r'E:\RawTriage'
|
|
DRY_RUN = False
|
|
|
|
# def constant_factory(value):
|
|
# return lambda: value
|
|
# fileidx = defaultdict(constant_factory(0))
|
|
|
|
fileidx = defaultdict(int)
|
|
|
|
CAMERAS = ("GoPro Hero3+", "Ricoh Theta V", "Ricoh Theta S", "Sony a5100", "Sony a65", "Sony a68", "Sony TRV-25E", "Fuji Finepix Real 3D W3", "DJI Mini 2", "Samsung Galaxy A40", "Samsung Galaxy A41")
|
|
|
|
|
|
def recurse(dir, md, camera=None):
|
|
for fp in dir.iterdir():
|
|
if fp.is_dir() and camera is None:
|
|
if fp.name in CAMERAS:
|
|
print(f"[{fp.name}] -------------------------------------------------")
|
|
recurse(fp, md, camera=fp.name)
|
|
elif camera:
|
|
recurse(fp, md, camera=camera)
|
|
if fp.is_dir() and camera is not None:
|
|
print(f"[{fp.name}] - [{camera}] ------------------------------------------------")
|
|
mo = re.match(r"(?P<dt>\S*)\s?(?P<title>.*)", fp.name)
|
|
md = mo.groupdict()
|
|
# title = md['title']
|
|
recurse(fp, md, camera=camera)
|
|
if not fp.is_file():
|
|
# print(f"{fp} neither dir nor file, skipping")
|
|
continue
|
|
# defaults
|
|
use_ts = True
|
|
use_camera = True
|
|
author = "ab"
|
|
mtime = fp.stat().st_mtime
|
|
rawdt = dt.datetime.fromtimestamp(mtime)
|
|
if fp.suffix.lower() in [".jpg"]:
|
|
try:
|
|
exif_dict = piexif.load(str(fp))
|
|
idto = exif_dict["Exif"][piexif.ExifIFD.DateTimeOriginal].decode("ascii")
|
|
rawdt = dt.datetime.strptime(idto, "%Y:%m:%d %H:%M:%S")
|
|
except:
|
|
print(f"no exif in {fp.name}, skipping")
|
|
continue
|
|
try:
|
|
model = exif_dict["0th"][piexif.ImageIFD.Model].decode("ascii")
|
|
except:
|
|
print(exif_dict)
|
|
model = None
|
|
use_camera = False
|
|
if model == 'Canon EOS 5D':
|
|
print(f"{fp.name} scanned photo, use directory date")
|
|
rawdt = dt.datetime.strptime(md['dt'], "%Y%m%d")
|
|
use_ts = False
|
|
if model in ('FinePix S602 ZOOM', 'Canon EOS 6D', 'NIKON D5100'):
|
|
author = "nn"
|
|
if model == 'PULP 4G':
|
|
author = "jb"
|
|
if model == 'ASUS_Z00ED':
|
|
author = "sb"
|
|
if model == 'SM-A405FN':
|
|
author = "ab"
|
|
if model == 'SM-A415F' or camera == "Samsung Galaxy A41":
|
|
author = "kb"
|
|
elif fp.suffix.lower() == ".heic":
|
|
use_camera = False
|
|
author = "kb"
|
|
elif fp.suffix.upper() == ".ARW":
|
|
use_camera = False
|
|
elif fp.suffix.upper() == ".MRW":
|
|
use_camera = False
|
|
elif fp.suffix.upper() == ".MPO":
|
|
use_camera = False
|
|
elif fp.suffix.upper() == ".MP4":
|
|
pass
|
|
elif fp.suffix.upper() == ".MTS":
|
|
pass
|
|
elif fp.suffix.upper() == ".AVI":
|
|
pass
|
|
else:
|
|
continue
|
|
year = rawdt.year
|
|
day = f"{rawdt:%Y%m%d}"
|
|
ts = f"{rawdt:%H%M%S}"
|
|
stem = f"{author}-{day}"
|
|
if use_ts:
|
|
stem += f"-{ts}"
|
|
else:
|
|
index = fileidx[day] + 1
|
|
fileidx[day] = index
|
|
stem += f"-{index:04}"
|
|
if use_camera:
|
|
stem += f"-{camera}"
|
|
rename(fp, fp.parent / f"{stem}{fp.suffix}")
|
|
# rename derivative files
|
|
i = len(fp.stem)
|
|
dvs = dir.rglob(f"{fp.stem}*.*")
|
|
for dv in dvs:
|
|
if dv.name == fp.name:
|
|
continue
|
|
# print(fp.name, stem, dv.name)
|
|
rename(dv, dv.parent / f"{stem}{dv.name[i:]}")
|
|
|
|
|
|
def rename(old, new):
|
|
print(old.name, "->", new.name)
|
|
if not DRY_RUN:
|
|
if new.exists():
|
|
if old == new:
|
|
print(f"skipped {old.name}, {new.name}, already exists")
|
|
else:
|
|
for c in "abcdefghijklmnopqrstuvwxyz":
|
|
alt = new.parent / f"{new.stem}{c}{new.suffix}"
|
|
if not alt.exists():
|
|
old.rename(alt)
|
|
break
|
|
else:
|
|
old.rename(new)
|
|
|
|
|
|
recurse(Path(SRC), None)
|