diff --git a/.project b/.project new file mode 100644 index 0000000..c031460 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + media-scripts + + + + + + org.python.pydev.PyDevBuilder + + + + + + org.python.pydev.pythonNature + + diff --git a/.pydevproject b/.pydevproject new file mode 100644 index 0000000..13cd160 --- /dev/null +++ b/.pydevproject @@ -0,0 +1,8 @@ + + + +/${PROJECT_DIR_NAME} + +python interpreter +Default + diff --git a/correct_finepix.py b/correct_finepix.py new file mode 100644 index 0000000..2331d48 --- /dev/null +++ b/correct_finepix.py @@ -0,0 +1,37 @@ +#!python3 + +# https://github.com/hMatoba/Piexif +# http://ce3wiki.theturninggate.net/doku.php?id=file_name_convention +# destination: // /ab---.jpg + +from pathlib import Path +import datetime as dt +import piexif + +SRC = r'E:\RawByDateArchive' + +for raw in Path(SRC).glob("**/*.jpg"): + fn = raw.name + if not raw.is_file(): + print(f"skipped {fn}") + continue + exif_dict = piexif.load(str(raw)) + try: + model = exif_dict["0th"][piexif.ImageIFD.Model].decode("ascii") + idto = exif_dict["Exif"][piexif.ExifIFD.DateTimeOriginal].decode("ascii") + except: + continue + if model != 'FinePix REAL 3D W3': + continue + rawdt = dt.datetime.strptime(idto,"%Y:%m:%d %H:%M:%S") + year = rawdt.year + day = f"{rawdt:%Y%m%d}" + ts = f"{rawdt:%H%M%S}" + destdir = raw.parent + stem = f"ab-{day}-{ts}" + destfn = destdir / f"{stem}{raw.suffix}" + if destfn.exists(): + print(f'skipped {destfn}, already exists') + continue + print(fn, "->", destfn) + raw.rename(destfn) diff --git a/cp_exif.py b/cp_exif.py new file mode 100644 index 0000000..2fffb83 --- /dev/null +++ b/cp_exif.py @@ -0,0 +1,26 @@ +#!python3 + +# https://github.com/hMatoba/Piexif +# http://ce3wiki.theturninggate.net/doku.php?id=file_name_convention +# destination: // /ab---.jpg + +from pathlib import Path +import datetime as dt +import piexif +import re + +SRC = r'E:\RawByUser\Andreas\Fuji Finepix 3D W3\Adjusted' +DEST = r'E:\RawByUser\Andreas\Fuji Finepix 3D W3\2D' + +src = Path(SRC) +for raw in src.glob("*.mpo"): + fn = raw.name + if not raw.is_file(): + print(f"skipped {fn}") + continue + destfn = Path(DEST) / f"{raw.stem}.jpg" + if not destfn.exists(): + print(f'skipped {destfn}, missing') + continue + print(f"{fn}", "->", destfn) + piexif.transplant(str(raw), str(destfn)) diff --git a/del_empty_folders.py b/del_empty_folders.py new file mode 100644 index 0000000..9386c59 --- /dev/null +++ b/del_empty_folders.py @@ -0,0 +1,33 @@ +#!python3 + +# set mtime for DV files from filename + +# https://github.com/hMatoba/Piexif +# http://ce3wiki.theturninggate.net/doku.php?id=file_name_convention +# destination: // /ab---.jpg + +from pathlib import Path +import datetime as dt +import piexif +from collections import defaultdict +import re +import os + +src = Path(r'E:\MediaArchive\Andreas\MaxQByDate') +dry_run = True + +for year in src.iterdir(): + if not year.is_dir(): + continue + for day in year.iterdir(): + if not day.is_dir(): + continue + files = list(day.iterdir()) + file_count = len(files) + if file_count > 0: + continue + if not re.match("\d{8}", day.name): + continue + print(f"{file_count:3} files in {day.name}") + if not dry_run: + day.rmdir() \ No newline at end of file diff --git a/dv.kds b/dv.kds new file mode 100644 index 0000000..f0d5e37 --- /dev/null +++ b/dv.kds @@ -0,0 +1,7 @@ +S'(?P
\\S*)\\s?(?P.*)' +p1 +.S'20030215' +p2 +.I0 +.S'' +. \ No newline at end of file diff --git a/dv_avi.kds b/dv_avi.kds new file mode 100644 index 0000000..3089233 --- /dev/null +++ b/dv_avi.kds @@ -0,0 +1,7 @@ +S'ab-(?P<dat>\\d{8})-(?P<title>[\\s\\w]+)-(?P<tim>\\d{6})-(?P<camera>[\\w\\s]+).avi' +p1 +.S'ab-20030215-Familienskifahren Saas Fee-121807-Sony TRV_25E.avi' +p2 +.I0 +.S'' +. \ No newline at end of file diff --git a/exif_dump.py b/exif_dump.py new file mode 100644 index 0000000..cbc8e46 --- /dev/null +++ b/exif_dump.py @@ -0,0 +1,27 @@ +#!python3 + +import sys +from pathlib import Path +import datetime as dt +import piexif + + +def dump(fn): + exif_dict = piexif.load(fn) + for ifd_name in exif_dict: + print("\n{0} IFD:".format(ifd_name)) + for key in exif_dict[ifd_name]: + try: + tag = piexif.TAGS[ifd_name][key]['name'] + try: + print(key, tag, exif_dict[ifd_name][key][:40]) + except: + print(key, tag, exif_dict[ifd_name][key]) + except: + pass + print(exif_dict["0th"][piexif.ImageIFD.DateTime]) + print(exif_dict["Exif"][piexif.ExifIFD.DateTimeOriginal]) + + +if __name__ == "__main__": + dump(sys.argv[1]) \ No newline at end of file diff --git a/m4v.kds b/m4v.kds new file mode 100644 index 0000000..d635764 --- /dev/null +++ b/m4v.kds @@ -0,0 +1,7 @@ +S'(?P<author>[^-]*)-(?P<dt>\\S*)-(?P<model>[^-]*)(-\\S+)?.m4v' +p1 +.S'Ab-20160506-111908-Sony A5100-1.m4v' +p2 +.I0 +.S'' +. \ No newline at end of file diff --git a/merge_photos.py b/merge_photos.py new file mode 100644 index 0000000..7c8a311 --- /dev/null +++ b/merge_photos.py @@ -0,0 +1,44 @@ +#!python3 + +# https://github.com/hMatoba/Piexif +# http://ce3wiki.theturninggate.net/doku.php?id=file_name_convention + +from pathlib import Path +import datetime as dt +import piexif +from collections import defaultdict +import re + +src = Path(r'E:\MediaArchive\Andreas\MaxQByDate\2005\Uncategorized') +dest = Path(r'E:\MediaArchive\Andreas\MaxQByDate') +dry_run = False + +for suffix in ("jpg",): + for pic in src.rglob(f"*.{suffix}"): + try: + exif_dict = piexif.load(str(pic)) + idto = exif_dict["Exif"][piexif.ExifIFD.DateTimeOriginal].decode("ascii") + picdt = dt.datetime.strptime(idto,"%Y:%m:%d %H:%M:%S") + except: + print(f'exif failed {pic.name}, using file date') + mtime = pic.stat().st_mtime + picdt = dt.datetime.fromtimestamp(mtime) + # create new dir with exif date and original title + title = pic.parts[-2] + mo = re.match("\d{8}",title) + if mo is None: + pic_dir = dest / str(picdt.year) / f"{picdt:%Y%m%d} {title}" + else: + pic_dir = dest / str(picdt.year) / f"{title}" + if not pic_dir.exists(): + if not dry_run: + print(f"creating {pic_dir}") + pic_dir.mkdir(parents=True) + pic_n = pic_dir / f"ab-{picdt:%Y%m%d}-{picdt:%H%M%S}{pic.suffix}" + n = 1 + while pic_n.exists(): + pic_n = pic_dir / f"ab-{picdt:%Y%m%d}-{picdt:%H%M%S}-{n:02}{pic.suffix}" + n += 1 + print(pic.name, "->", pic_n) + if not dry_run: + pic.rename(pic_n) diff --git a/mover.py b/mover.py new file mode 100644 index 0000000..2bce811 --- /dev/null +++ b/mover.py @@ -0,0 +1,50 @@ +#!python3 + +# 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 + +SRC = r'E:\MediaByTarget\Plex\Home Videos' +DEST = r'E:\Users\Andreas\RawByDate' +author = 'ab' +dry_run = False + +def constant_factory(value): + return lambda: value + +dateidx = defaultdict(constant_factory(0)) + +for suffix in ("jpg", "gif", "png", "mp4", "avi", "mov"): + for raw in Path(SRC).rglob(f"*.{suffix}"): + fn = raw.name + if not raw.is_file(): + print(f"skipped {fn}") + continue + try: + exif_dict = piexif.load(str(raw)) + idto = exif_dict["Exif"][piexif.ExifIFD.DateTimeOriginal].decode("ascii") + rawdt = dt.datetime.strptime(idto,"%Y:%m:%d %H:%M:%S") + except: + print(f'exif failed {fn}, using file date') + mtime = raw.stat().st_mtime + rawdt = dt.datetime.fromtimestamp(mtime) + year = rawdt.year + day = f"{rawdt:%Y%m%d}" + ts = f"{rawdt:%H%M%S}" + destdir = Path(DEST, f"{year}",f"{day}") + if not destdir.exists() and not dry_run: + print(f'creating {destdir}') + destdir.mkdir(parents=True) + destfn = destdir / f"{author}-{day}-{ts}{raw.suffix}" + if destfn.exists(): + index = dateidx[day] + 1 + dateidx[day] = index + destfn = destdir / f"{author}-{day}-{index:04}{raw.suffix}" + print(fn, "->", destfn) + if not dry_run: + raw.rename(destfn) diff --git a/mv_arw.py b/mv_arw.py new file mode 100644 index 0000000..20c0183 --- /dev/null +++ b/mv_arw.py @@ -0,0 +1,41 @@ +#!python3 + +# 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 = Path(r'E:\MediaArchive\Andreas\RawByDate') +dest = Path(r'E:\MediaArchive\Andreas\RawByCamera\Sony a5100') +dry_run = False + +for mrw in src.rglob("*.arw"): + mo = re.match("ab-(?P<dt>\S*-\S*).arw", mrw.name) + if mo is None: + print(f"skipped {mrw.name}, no match") + continue + md = mo.groupdict() + try: + mrwdt = dt.datetime.strptime(md['dt'],"%Y%m%d-%H%M%S") + except: + print(f"skipped {mrw.name}, unknown format") + continue + # move avi to raw Sony + mrw_dir = dest / str(mrwdt.year) / f"{mrwdt:%Y%m%d}" + mrw_n = mrw_dir / mrw.name + if not mrw_dir.exists(): + if not dry_run: + print(f"creating {mrw_dir}") + mrw_dir.mkdir(parents=True) + print(mrw.name, "->", mrw_n) + if not mrw_n.exists(): + if not dry_run: + mrw.rename(mrw_n) + else: + print(f"skipped {mrw.name}, {mrw_n}, already exists") + \ No newline at end of file diff --git a/mv_dng.py b/mv_dng.py new file mode 100644 index 0000000..b5c4cab --- /dev/null +++ b/mv_dng.py @@ -0,0 +1,45 @@ +#!python3 + +# 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 = Path(r'E:\MediaArchive\Andreas\MaxQByDate') +dest1 = Path(r"E:\MediaArchive\Andreas\RawByCamera\Minolta Dynax 5") +dest2 = Path(r'E:\MediaArchive\Andreas\RawByCamera\Sony a5100') +dry_run = False + +for mrw in src.rglob("*.dng"): + mo = re.match("ab-(?P<dt>\S*-\S*).dng", mrw.name) + if mo is None: + print(f"skipped {mrw.name}, no match") + continue + md = mo.groupdict() + try: + mrwdt = dt.datetime.strptime(md['dt'],"%Y%m%d-%H%M%S") + except: + print(f"skipped {mrw.name}, unknown format") + continue + # move avi to raw Sony + if mrwdt.year > 2010: + mrw_dir = dest2 / str(mrwdt.year) / f"{mrwdt:%Y%m%d}" + else: + mrw_dir = dest1 / str(mrwdt.year) / f"{mrwdt:%Y%m%d}" + mrw_n = mrw_dir / mrw.name + if not mrw_dir.exists(): + if not dry_run: + print(f"creating {mrw_dir}") + mrw_dir.mkdir(parents=True) + print(mrw.name, "->", mrw_n) + if not mrw_n.exists(): + if not dry_run: + mrw.rename(mrw_n) + else: + print(f"skipped {mrw.name}, {mrw_n}, already exists") + \ No newline at end of file diff --git a/mv_dv_avi.py b/mv_dv_avi.py new file mode 100644 index 0000000..5a709e8 --- /dev/null +++ b/mv_dv_avi.py @@ -0,0 +1,38 @@ +#!python3 + +# 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 +import re + +SRC = r'E:\RawByUser\Andreas\Sony TRV-25E\DV' +DEST = r'E:\VideoByDateArchive' + +src = Path(SRC) +for raw in src.glob("*.avi"): + fn = raw.name + if not raw.is_file(): + print(f"skipped {fn}") + continue + mo = re.match("(?P<dt>\S*\s\S*)(\s(?P<title>.*))?.avi", fn) + md = mo.groupdict() + rawdt = dt.datetime.strptime(md['dt'],"%Y-%m-%d %H.%M.%S") + title = md['title'] + year = rawdt.year + day = f"{rawdt:%Y%m%d}" + ts = f"{rawdt:%H%M%S}" + destdir = Path(DEST, f"{year}",f"{day}") + if not destdir.exists(): + print(f'creating {destdir}') + destdir.mkdir(parents=True) + stem = f"ab-{day}-{ts}-{title}-Sony TRV_25E" + destfn = destdir / f"{stem}{raw.suffix}" + if destfn.exists(): + print(f'skipped {destfn}, already exists') + continue + print(f"{fn}", "->", destfn) + raw.rename(destfn) diff --git a/mv_hd_mp4.py b/mv_hd_mp4.py new file mode 100644 index 0000000..6371fc4 --- /dev/null +++ b/mv_hd_mp4.py @@ -0,0 +1,45 @@ +#!python3 + +# 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 = Path(r'E:\MediaByTarget\Plex\Home Videos') +dest = Path(r'E:\MediaArchive\Andreas\RawByDate') +author = 'ab' +dry_run = False + +# def constant_factory(value): +# return lambda: value +# fileidx = defaultdict(constant_factory(0)) + +fileidx = defaultdict(int) + +for mp4 in src.rglob("*-HD.mp4"): + mo = re.match("(?P<dt>\S*-\S*)-HD.mp4", mp4.name) + if mo is None: + print(f"skipped {mp4.name}, no match") + continue + md = mo.groupdict() + mp4dt = dt.datetime.strptime(md['dt'],"%Y%m%d-%H%M%S") + # move avi to raw Sony + mp4_fn = f"ab-{md['dt']}-Panasonic HDC_SD99.mp4" + mp4_dir = dest / str(mp4dt.year) / f"{mp4dt:%Y%m%d}" + mp4_n = mp4_dir / mp4_fn + if not mp4_dir.exists(): + print(f"creating {mp4_dir}") + if not dry_run: + mp4_dir.mkdir(parents=True) + print(mp4.name, "->", mp4_n) + if not mp4_n.exists(): + if not dry_run: + mp4.rename(mp4_n) + else: + print(f"skipped {mp4.name}, {mp4_n}, already exists") + \ No newline at end of file diff --git a/mv_lumia.py b/mv_lumia.py new file mode 100644 index 0000000..68e6ec3 --- /dev/null +++ b/mv_lumia.py @@ -0,0 +1,42 @@ +#!python3 + +# 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 + +# SRC = r'E:\RawByUser\Andreas\Microsoft Lumia 640' +# SRC = r'E:\RawByUser\Andreas\Samsung DV-150' +SRC = r'E:\RawByUser\Andreas\Sony K800i' +DEST = r'E:\VideoByDateArchive' + +src = Path(SRC) +for raw in src.glob("*.3GP"): + fn = raw.name + if not raw.is_file(): + print(f"skipped {fn}") + continue + try: + # rawdt = dt.datetime.strptime(fn,"ab-%Y%m%d-%H%M%S-Samsung DV-150.MP4") + rawdt = dt.datetime.strptime(fn,"ab-%Y%m%d-%H%M%S-Sony K800i.3GP") + except: + print(f'exif failed {fn}, using file date') + mtime = raw.stat().st_mtime + rawdt = dt.datetime.fromtimestamp(mtime) + year = rawdt.year + day = f"{rawdt:%Y%m%d}" + ts = f"{rawdt:%H%M%S}" + destdir = Path(DEST, f"{year}",f"{day}") + if not destdir.exists(): + print(f'creating {destdir}') + destdir.mkdir(parents=True) + # stem = f"kb-{day}-{ts}" + destfn = destdir / f"{fn}" + if destfn.exists(): + print(f'skipped {destfn}, already exists') + continue + print(f"{fn}", "->", destfn) + raw.rename(destfn) diff --git a/mv_mrw.py b/mv_mrw.py new file mode 100644 index 0000000..33fdd84 --- /dev/null +++ b/mv_mrw.py @@ -0,0 +1,37 @@ +#!python3 + +# 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 = Path(r'E:\MediaArchive\Andreas\RawByDate') +dest = Path(r'E:\MediaArchive\Andreas\RawByCamera\Minolta Dynax 5') +dry_run = False + +for mrw in src.rglob("*.mrw"): + mo = re.match("ab-(?P<dt>\S*-\S*).mrw", mrw.name) + if mo is None: + print(f"skipped {mrw.name}, no match") + continue + md = mo.groupdict() + mrwdt = dt.datetime.strptime(md['dt'],"%Y%m%d-%H%M%S") + # move avi to raw Sony + mrw_dir = dest / str(mrwdt.year) / f"{mrwdt:%Y%m%d}" + mrw_n = mrw_dir / mrw.name + if not mrw_dir.exists(): + print(f"creating {mrw_dir}") + if not dry_run: + mrw_dir.mkdir(parents=True) + print(mrw.name, "->", mrw_n) + if not mrw_n.exists(): + if not dry_run: + mrw.rename(mrw_n) + else: + print(f"skipped {mrw.name}, {mrw_n}, already exists") + \ No newline at end of file diff --git a/mv_samsung.py b/mv_samsung.py new file mode 100644 index 0000000..05ae8b5 --- /dev/null +++ b/mv_samsung.py @@ -0,0 +1,41 @@ +#!python3 + +# 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 + +SRC = r'E:\RawByUser\Andreas\Samsung DV-150' +DEST = r'E:\RawByDateArchive' + +src = Path(SRC) +for raw in src.glob("**/*.JPG"): + fn = raw.name + if not raw.is_file(): + print(f"skipped {fn}") + continue + try: + exif_dict = piexif.load(str(raw)) + idto = exif_dict["Exif"][piexif.ExifIFD.DateTimeOriginal].decode("ascii") + rawdt = dt.datetime.strptime(idto,"%Y:%m:%d %H:%M:%S") + except: + print(f'skipped {fn}, using file date') + mtime = raw.stat().st_mtime + rawdt = dt.datetime.fromtimestamp(mtime) + year = rawdt.year + day = f"{rawdt:%Y%m%d}" + ts = f"{rawdt:%H%M%S}" + destdir = Path(DEST, f"{year}",f"{day}") + if not destdir.exists(): + print(f'creating {destdir}') + destdir.mkdir() + stem = f"ab-{day}-{ts}" + destfn = destdir / f"{stem}{raw.suffix}" + if destfn.exists(): + print(f'skipped {destfn}, already exists') + continue + print(f"{fn}", "->", destfn) + raw.rename(destfn) diff --git a/mv_sd_mp4.py b/mv_sd_mp4.py new file mode 100644 index 0000000..565030a --- /dev/null +++ b/mv_sd_mp4.py @@ -0,0 +1,45 @@ +#!python3 + +# 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 = Path(r'E:\MediaByTarget\Plex\Home Videos') +dest = Path(r'E:\MediaArchive\Andreas\RawByDate') +author = 'ab' +dry_run = False + +# def constant_factory(value): +# return lambda: value +# fileidx = defaultdict(constant_factory(0)) + +fileidx = defaultdict(int) + +for mp4 in src.rglob("*-SD.mp4"): + mo = re.match("(?P<dt>\S*-\S*)-SD.mp4", mp4.name) + if mo is None: + print(f"skipped {mp4.name}, no match") + continue + md = mo.groupdict() + mp4dt = dt.datetime.strptime(md['dt'],"%Y%m%d-%H%M%S") + # move avi to raw Sony + mp4_fn = f"ab-{md['dt']}-Panasonic SDR_S7.mp4" + mp4_dir = dest / str(mp4dt.year) / f"{mp4dt:%Y%m%d}" + mp4_n = mp4_dir / mp4_fn + if not mp4_dir.exists(): + # print(f"creating {mp4_dir}") + if not dry_run: + mp4_dir.mkdir(parents=True) + print(mp4.name, "->", mp4_n) + if not mp4_n.exists(): + if not dry_run: + mp4.rename(mp4_n) + else: + print(f"skipped {mp4.name}, {mp4_n}, already exists") + \ No newline at end of file diff --git a/ren_dv_avi.py b/ren_dv_avi.py new file mode 100644 index 0000000..86c5da3 --- /dev/null +++ b/ren_dv_avi.py @@ -0,0 +1,34 @@ +#!python3 + +# replace avi originals by mp4 + +# 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 +import os + +src = Path(r'E:\MediaArchive\Andreas\RawByCamera\Sony TRV-25E') +DRY_RUN = False + +def rename(old, new): + print(old.name, "->", new.name) + if not DRY_RUN: + if not new.exists(): + old.rename(new) + else: + print(f"skipped {old.name}, {new.name}, already exists") + +for raw in src.glob("*.avi"): + mo = re.match("ab-(?P<dat>\d{8})-(?P<title>[&\s\w]+)-(?P<tim>\d{6})-(?P<camera>[\w\s]+).avi", raw.name) + if mo is None: + # print(f"skipped {raw.name}, no match") + continue + md = mo.groupdict() + fn = f"ab-{md['dat']}-{md['tim']}-{md['title']}-{md['camera']}{raw.suffix}" + rename(raw, raw.parent / fn) diff --git a/ren_finepix.py b/ren_finepix.py new file mode 100644 index 0000000..11cf9a4 --- /dev/null +++ b/ren_finepix.py @@ -0,0 +1,43 @@ +#!python3 + +# 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 +import re + +SRC = r'E:\RawByUser\Andreas\Fuji Finepix 3D W3\Adjusted' +# DEST = r'E:\VideoByDateArchive' + +src = Path(SRC) +for raw in src.glob("*.mpo"): + fn = raw.name + if not raw.is_file(): + print(f"skipped {fn}") + continue + try: + exif_dict = piexif.load(str(raw)) + idto = exif_dict["Exif"][piexif.ExifIFD.DateTimeOriginal].decode("ascii") + rawdt = dt.datetime.strptime(idto,"%Y:%m:%d %H:%M:%S") + except: + # print(f'skipped {fn}, using file date') + mtime = raw.stat().st_mtime + rawdt = dt.datetime.fromtimestamp(mtime) + year = rawdt.year + day = f"{rawdt:%Y%m%d}" + ts = f"{rawdt:%H%M%S}" + stem = f"ab-{day}-{ts}" + destdir = raw.parent + # destdir = Path(DEST, f"{year}",f"{day}") + # if not destdir.exists(): + # print(f'creating {destdir}') + # destdir.mkdir(parents=True) + destfn = destdir / f"{stem}{raw.suffix}" + # if destfn.exists(): + # print(f'skipped {destfn}, already exists') + # continue + print(f"{fn}", "->", destfn) + raw.rename(destfn) diff --git a/ren_title.py b/ren_title.py new file mode 100644 index 0000000..e13256e --- /dev/null +++ b/ren_title.py @@ -0,0 +1,81 @@ +#!python3 + +# 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:\MediaArchive\Andreas\RawByDate\2004' +# camera = "Minolta" +author = 'ab' +dry_run = False + +# def constant_factory(value): +# return lambda: value +# fileidx = defaultdict(constant_factory(0)) + +fileidx = defaultdict(int) + +for daydir in Path(SRC).iterdir(): + mo = re.match("(?P<dt>\S*)\s(?P<title>.*)", daydir.name) + md = mo.groupdict() + title = md['title'] + for raw in daydir.rglob(f"*.jpg"): + # check whether exif works + try: + exif_dict = piexif.load(str(raw)) + model = exif_dict["0th"][piexif.ImageIFD.Model].decode("ascii") + idto = exif_dict["Exif"][piexif.ExifIFD.DateTimeOriginal].decode("ascii") + rawdt = dt.datetime.strptime(idto,"%Y:%m:%d %H:%M:%S") + except: + model = None + print(f'exif failed {raw.name}, using file date') + mtime = raw.stat().st_mtime + rawdt = dt.datetime.fromtimestamp(mtime) + # digitized negative photo? + if model == 'Canon EOS 5D': + rawdt = dt.datetime.strptime(md['dt'],"%Y%m%d") + use_ts = False + else: + use_ts = True + if model == 'FinePix S602 ZOOM': + author = "nn" + else: + author = "ab" + year = rawdt.year + day = f"{rawdt:%Y%m%d}" + ts = f"{rawdt:%H%M%S}" + if use_ts: + destfn = raw.parent / f"{author}-{day}-{title}-{ts}{raw.suffix}" + else: + index = fileidx[day] + 1 + fileidx[day] = index + destfn = raw.parent / f"{author}-{day}-{title}-{index:04}{raw.suffix}" + # destfn = raw.parent / f"{author}-{day}-{title}-{index:04}-{camera}{raw.suffix}" + print(raw.name, "->", destfn.name) + if not dry_run: + if not destfn.exists(): + raw.rename(destfn) + else: + print(f"skipped {raw.name}, {destfn.name}, already exists") + camera = "Sony TRV_25E" + for raw in daydir.rglob(f"*.avi"): + mtime = raw.stat().st_mtime + rawdt = dt.datetime.fromtimestamp(mtime) + year = rawdt.year + day = f"{rawdt:%Y%m%d}" + ts = f"{rawdt:%H%M%S}" + index = fileidx[day] + 1 + fileidx[day] = index + destfn = raw.parent / f"{author}-{day}-{title}-{ts}-{camera}{raw.suffix}" + print(raw.name, "->", destfn.name) + if not dry_run: + if not destfn.exists(): + raw.rename(destfn) + else: + print(f"skipped {raw.name}, {destfn.name}, already exists") diff --git a/ren_triage.py b/ren_triage.py new file mode 100644 index 0000000..85c9cf4 --- /dev/null +++ b/ren_triage.py @@ -0,0 +1,121 @@ +#!python3 + +# 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 TRV-25E") + + +def recurse(dir, md, camera=None): + for fp in dir.iterdir(): + if fp.is_dir(): + if fp.name in CAMERAS: + recurse(fp, md, camera=fp.name) + elif camera: + recurse(fp, md, camera=camera) + else: + recurse(fp, md) + continue + 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() == ".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: + model = None + pass + 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" + elif fp.suffix.upper() == ".ARW": + use_camera = False + elif fp.suffix.upper() == ".MRW": + 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 not new.exists(): + old.rename(new) + else: + print(f"skipped {old.name}, {new.name}, already exists") + + +for daydir in Path(SRC).iterdir(): + if not daydir.is_dir(): + continue + if daydir.name != "Aquaris U Plus": + continue + print(f"[{daydir.name}] -------------------------------------------------") + mo = re.match("(?P<dt>\S*)\s?(?P<title>.*)", daydir.name) + md = mo.groupdict() + title = md['title'] + recurse(daydir, md, camera="Aquaris U Plus") diff --git a/rep_dv_avi_by_mp4.py b/rep_dv_avi_by_mp4.py new file mode 100644 index 0000000..4e93926 --- /dev/null +++ b/rep_dv_avi_by_mp4.py @@ -0,0 +1,48 @@ +#!python3 + +# replace avi originals by mp4 + +# 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 +import os + +plex = Path(r'E:\MediaByTarget\Plex\Home Videos') +rbd = Path(r"E:\MediaArchive\Andreas\RawByDate") +sony = Path(r"E:\MediaArchive\Andreas\RawByCamera\Sony TRV-25E") +author = 'ab' +dry_run = False + +for mp4 in plex.rglob("*-DV.mp4"): + mtime = mp4.stat().st_mtime + mp4dt = dt.datetime.fromtimestamp(mtime) + aviglob = f"ab-{mp4dt:%Y%m%d}*{mp4dt:%H%M%S}*Sony TRV_25E.avi" + avis = list(rbd.rglob(aviglob)) + if len(avis) != 1: + print(f"found {len(avis)} for {aviglob}") + continue + avi = avis[0] + # print(f"match {mp4.name} for {avi.name}") + # move avi to raw Sony + print(avi.name, "->", str(sony)) + avi_n = sony / avi.name + if not avi_n.exists(): + if not dry_run: + avi.rename(avi_n) + else: + print(f"skipped {avi.name}, {avi_n}, already exists") + # move mp4 to hires + mp4_fn = f"ab-{mp4dt:%Y%m%d}-{mp4dt:%H%M%S}-Sony TRV_25E.mp4" + mp4_n = avi.parent / mp4_fn + print(mp4.name, "->", mp4_n.name) + if not mp4_n.exists(): + if not dry_run: + mp4.rename(mp4_n) + else: + print(f"skipped {mp4.name}, {mp4_n}, already exists") diff --git a/rmorgdups.py b/rmorgdups.py new file mode 100644 index 0000000..588d88e --- /dev/null +++ b/rmorgdups.py @@ -0,0 +1,56 @@ +#!python3 + +# remove Minolta original duplicates + +# 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 + +SRC = r'E:\RawByDateArchive' +DEST = r'E:\RawByDateArchive' +MINOLTA = "Minolta Dynax 5" + +rbda = Path(SRC) +for yeardir in rbda.iterdir(): + if not yeardir.is_dir(): + continue + for daydir in yeardir.iterdir(): + minoltadir = Path(daydir,MINOLTA) + if not minoltadir.exists(): + continue + for raw in minoltadir.iterdir(): + fn = raw.name + if not raw.is_file(): + print(f'skipped {fn}') + continue + try: + exif_dict = piexif.load(str(raw)) + idto = exif_dict["Exif"][piexif.ExifIFD.DateTimeOriginal].decode("ascii") + rawdt = dt.datetime.strptime(idto,"%Y:%m:%d %H:%M:%S") + except: + # print(f'skipped {fn}, using file date') + mtime = raw.stat().st_mtime + rawdt = dt.datetime.fromtimestamp(mtime) + year = rawdt.year + day = f"{rawdt:%Y%m%d}" + ts = f"{rawdt:%H%M%S}" + destdir = Path(DEST, f"{year}",f"{day}") + if not destdir.exists(): + print(f'creating {destdir}') + destdir.mkdir() + stem = f"ab-{day}-{ts}" + destfn = destdir / f"{stem}{raw.suffix}" + print(f"{fn}", "->", destfn) + # check dng or mrw dup in daydir + dups = daydir.glob(f"{stem}.*") + for d in dups: + print(f"removing {d}") + d.unlink() + if destfn.exists(): + print(f'skipped {destfn}, already exists') + continue + raw.rename(destfn) diff --git a/set_dv_mtime.py b/set_dv_mtime.py new file mode 100644 index 0000000..0a7e0e5 --- /dev/null +++ b/set_dv_mtime.py @@ -0,0 +1,30 @@ +#!python3 + +# set mtime for DV files from filename + +# 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 +import os + +src = Path(r'E:\MediaByTarget\Plex\Home Videos') +author = 'ab' +dry_run = False + +for raw in src.rglob("*-DV.mp4"): + mo = re.match("(?P<dt>\S*-\S*)-DV.mp4", raw.name) + if mo is None: + print(f"skipped {raw.name}, no match") + continue + md = mo.groupdict() + rawdt = dt.datetime.strptime(md['dt'],"%Y%m%d-%H%M%S") + mtime = rawdt.timestamp() + atime = raw.stat().st_atime + print(f"setting {raw.name} to {rawdt}") + os.utime(raw, (atime, mtime)) diff --git a/set_hdc_mtime.py b/set_hdc_mtime.py new file mode 100644 index 0000000..037343b --- /dev/null +++ b/set_hdc_mtime.py @@ -0,0 +1,49 @@ +#!python3 + +# set mtime for handbrake mp4 files from filename + +# 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 +import os + +DRY_RUN = False + +def rename(old, new): + print(old.name, "->", new.name) + if not DRY_RUN: + if not new.exists(): + old.rename(new) + else: + print(f"skipped {old.name}, {new.name}, already exists") + +src = Path(r'D:\Videos') +tim = Path(r'E:\MediaArchive\Andreas\RawByCamera\Panasonic HDC-SD99\20150412-20161209 Card\PRIVATE\AVCHD\BDMV\STREAM') + +for raw in src.glob("*.m4v"): + mo = re.match("(?P<seq>\d+)-\d+.m4v", raw.name) + if mo is None: + print(f"skipped {raw.name}, no match") + continue + md = mo.groupdict() + mtsn = f"{md['seq']}.MTS" + mts_ = list(tim.glob(mtsn)) + if len(mts_) != 1: + print(f"skipped {mtsn}, no match") + continue + mts=mts_[0] + stat = mts.stat() + mtime = stat.st_mtime + atime = stat.st_atime + rawdt = dt.datetime.fromtimestamp(mtime) + print(f"{raw.name} -> {rawdt}") + if not DRY_RUN: + os.utime(raw, (atime, mtime)) + fn = f"ab-{rawdt:%Y%m%d-%H%M%S}-Panasonic HDC_SD99{raw.suffix}" + rename(raw, raw.parent / fn) diff --git a/set_m4v_mtime.py b/set_m4v_mtime.py new file mode 100644 index 0000000..61d8e2b --- /dev/null +++ b/set_m4v_mtime.py @@ -0,0 +1,41 @@ +#!python3 + +# set mtime for handbrake mp4 files from filename + +# 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 +import os + +DRY_RUN = False + +def rename(old, new): + print(old.name, "->", new.name) + if not DRY_RUN: + if not new.exists(): + old.rename(new) + else: + print(f"skipped {old.name}, {new.name}, already exists") + +src = Path(r'D:\Videos') + +for raw in src.glob("*.m4v"): + mo = re.match("(?P<author>[^-]*)-(?P<dt>\S*)-(?P<model>[^-]*)(-\S+)?.m4v", raw.name) + if mo is None: + print(f"skipped {raw.name}, no match") + continue + md = mo.groupdict() + rawdt = dt.datetime.strptime(md['dt'],"%Y%m%d-%H%M%S") + mtime = rawdt.timestamp() + atime = raw.stat().st_atime + print(f"setting {raw.name} to {rawdt}") + if not DRY_RUN: + os.utime(raw, (atime, mtime)) + fn = f"{md['author'].lower()}-{md['dt']}-{md['model']}{raw.suffix}" + rename(raw, raw.parent / fn)