Created
December 28, 2024 22:02
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@echo off | |
C:\Users\jing\anaconda3\python.exe "C:\Users\jing\AppData\Local\Microsoft\WindowsApps\rename_photos.py" %* | |
pause |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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