Skip to content

Instantly share code, notes, and snippets.

@psiborg
Created December 28, 2024 22:02
Show Gist options
  • Save psiborg/ca61fb9f7e77c645f883e55eeb5a25e3 to your computer and use it in GitHub Desktop.
Save psiborg/ca61fb9f7e77c645f883e55eeb5a25e3 to your computer and use it in GitHub Desktop.
Drag-and-drop files from Windows Explorer on to this batch script to rename photos using EXIF data
@echo off
C:\Users\jing\anaconda3\python.exe "C:\Users\jing\AppData\Local\Microsoft\WindowsApps\rename_photos.py" %*
pause
import sys
import os
from PIL import Image
from datetime import datetime
LOG_FILE = "rename_log.txt"
def get_exif_datetime(file_path):
"""Extract the datetime from EXIF data if available."""
try:
image = Image.open(file_path)
exif_data = image._getexif()
if exif_data:
date_time_original = exif_data.get(36867) # Tag for DateTimeOriginal
if date_time_original:
return datetime.strptime(date_time_original, '%Y:%m:%d %H:%M:%S')
except Exception as e:
print(f"Error reading EXIF data from {file_path}: {e}")
return None
def rename_file(file_path, new_name):
"""Rename the file to the new name."""
directory, _ = os.path.split(file_path)
new_path = os.path.join(directory, new_name)
os.rename(file_path, new_path)
return new_path
def log_rename(original, new):
"""Log the renaming for potential undo."""
with open(LOG_FILE, "a") as log:
log.write(f"{original} -> {new}\n")
def undo_rename():
"""Undo renaming by reading the log file."""
if not os.path.exists(LOG_FILE):
print("No log file found. Nothing to undo.")
return
with open(LOG_FILE, "r") as log:
lines = log.readlines()
for line in reversed(lines):
try:
original, new = line.strip().split(" -> ")
if os.path.exists(new):
os.rename(new, original)
print(f"Reverted: {new} -> {original}")
else:
print(f"File not found for undo: {new}")
except Exception as e:
print(f"Error reverting: {line.strip()} - {e}")
# Clear the log file after undo
open(LOG_FILE, "w").close()
print("Undo complete. Log cleared.")
def main():
# Check if undo mode is requested
if len(sys.argv) > 1 and sys.argv[1] == "--undo":
undo_rename()
return
# Get arguments
args = sys.argv[1:]
if not args:
print("Drag and drop files onto this script to rename them.")
print("Use --undo to revert the last renaming operation.")
return
# Optional prefix
prefix = "photo-"
if args[0].startswith("--prefix="):
prefix = args[0].split("=", 1)[1]
args = args[1:]
sequential_number = 1
for file_path in args:
if not os.path.isfile(file_path):
print(f"Skipping non-file: {file_path}")
continue
original_path = file_path
# Get EXIF datetime
date_time = get_exif_datetime(file_path)
if date_time:
# Rename using EXIF datetime
new_name = date_time.strftime("%Y%m%d-%H%M%S") + os.path.splitext(file_path)[1]
else:
# Rename using prefix and sequential number
new_name = f"{prefix}{sequential_number:04d}" + os.path.splitext(file_path)[1]
sequential_number += 1
try:
new_path = rename_file(file_path, new_name)
log_rename(original_path, new_path)
print(f"Renamed: {original_path} -> {new_path}")
except Exception as e:
print(f"Error renaming {file_path}: {e}")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment