dotfiles/config/scripts/camera_name_date

115 lines
3.3 KiB
Python
Executable file

#!/usr/bin/env python3
"""
Same as picture_name_date
except it's tailored for OpenCamera.
It uses filenames, that way:
- Easier to get metadata
- JPG/DNG, MP4/SRT keep the same filename
"""
import argparse
import logging
import os
import re
import coloredlogs
log = logging.getLogger(__name__)
coloredlogs.install(level="DEBUG", fmt="%(levelname)s %(message)s", logger=log)
PATTERNS = [
re.compile( # OpenCamera
r"^(?P<type>IMG|VID)_"
# No TRIM. We don't want those as they're a short copy of an existing VID.
r"(?P<Y>\d\d\d\d)(?P<M>\d\d)(?P<D>\d\d)_"
r"(?P<h>\d\d)(?P<m>\d\d)(?P<s>\d\d)"
r"(?P<dup>_(\d+))?"
r"(?P<spec>_(PANO|HDR))?"
r"\.(?P<ext>jpg|dng|mp4|srt)$"
),
re.compile( # Samsung camera app (?)
r"(?P<Y>\d\d\d\d)(?P<M>\d\d)(?P<D>\d\d)_"
r"(?P<h>\d\d)(?P<m>\d\d)(?P<s>\d\d)"
r"\.(?P<ext>jpg|mp4)$"
),
re.compile( # Telegram Media Downloader photo
r"photo_"
r"(?P<Y>\d\d\d\d)-(?P<M>\d\d)-(?P<D>\d\d)_"
r"(?P<h>\d\d)-(?P<m>\d\d)-(?P<s>\d\d)"
r"(?P<dup>_\d{19})"
r"\.(?P<ext>jpg)$"
), # Time of publication, not time of photo!
re.compile( # Telegram Media Downloader video
r"video_"
r"(?P<Y>\d\d\d\d)-(?P<M>\d\d)-(?P<D>\d\d)_"
r"(?P<h>\d\d)-(?P<m>\d\d)-(?P<s>\d\d)"
r"(?P<dup>_\d{19})"
r"\.(?P<ext>mp4)$"
), # Time of publication, not time of video!
]
def main(args: argparse.Namespace) -> None:
for root, _, files in os.walk(args.dir):
for filename in files:
full_path = os.path.join(root, filename)
for pattern in PATTERNS:
match = re.match(pattern, filename)
if match:
break
else:
log.warning(f"{full_path} doesn't any pattern")
continue
# Build new filename
m = match.groupdict()
new_filename = (
f"{m['Y']}-{m['M']}-{m['D']}_"
f"{m['h']}-{m['m']}-{m['s']}"
f"{m.get('dup') or ''}"
f"{m.get('spec') or ''}"
f"{args.suffix}"
f".{m['ext']}"
)
new_path = os.path.join(args.dir, new_filename)
# TODO Allow keeping image in same folder
# Rename file
if full_path == new_path:
log.debug(f"{full_path} already at required filename")
continue
log.info(f"{full_path}\t{new_path}")
if os.path.exists(new_path):
raise FileExistsError(f"{new_path} already exists!")
if not args.dry:
os.rename(full_path, new_path)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Rename OpenCamera files based on their dates"
)
parser.add_argument(
"dir",
metavar="DIRECTORY",
type=str,
default=".",
nargs="?",
help="Directory containing the pictures",
)
parser.add_argument(
"-d",
"--dry",
action="store_true",
help="Do not actually rename, just show old and new path",
)
parser.add_argument(
"-s",
"--suffix",
default="",
help="Text to add before the extension",
)
args = parser.parse_args()
main(args)