All of my digital photos are in a very badly organised set of folders, some of which have names of the event. My most recent photos all come from my phone automatically uploaded to my laptop via OneDrive, in one folder. Every few months (turning into years), I delete the photos from my phone to free up speace. I’m getting fed up of sorting these manually so I’ve decided I’m going to organise by year and month. Not wanting to go through all my old digital photos, a python script to process them all seemed like the way forward.

Although I could write the script myself, this was a perfect case for ChatGPT! The following code is entirely created by the generative AI, and I only had to ask it a couple of extra things, such as what to do when EXIF data did not exist, and also to prepend the file name with the source folder (so that at least some of my original naming was not lost! I didn’t need to do any manually tweaking of the code, except to add the source and destination folders – and it processed 100GB of photos in no time. Even better, after a few months, I can just run the same script again to move my latest photos and organise them by month and year. Job done.

import os
import shutil
from datetime import datetime
import exifread

# Source directory containing the photo album
source_directory = '/path/to/source/

# Destination directory where files will be organized
destination_directory = '/path/to/destination'

# Function to extract creation date from EXIF metadata, or return None if there's an error
def get_creation_date(file_path):
    try:
        with open(file_path, 'rb') as f:
            tags = exifread.process_file(f)
            date_taken = tags.get('EXIF DateTimeOriginal')
            if date_taken:
                return datetime.strptime(str(date_taken), '%Y:%m:%d %H:%M:%S')
    except Exception:
        pass
    return None

# Iterate through the source directory
for root, dirs, files in os.walk(source_directory):
    for file in files:
        print(file)
        file_path = os.path.join(root, file)

        creation_date = get_creation_date(file_path)
        if creation_date:
            # Extract year and month from the creation date
            year = creation_date.strftime('%Y')
            month = creation_date.strftime('%m')

            # Get the name of the immediate source directory
            source_directory_name = os.path.basename(root)

            # Prepend the directory name to the filename
            new_filename = f"{source_directory_name}_{file}"

            # Create destination directory if it doesn't exist
            dest_dir = os.path.join(destination_directory, year, month)
            os.makedirs(dest_dir, exist_ok=True)

            # Copy the file to the destination directory with the new filename
            shutil.copy(file_path, os.path.join(dest_dir, new_filename))
        else:
            # Copy the file to the destination directory while preserving the original path
            rel_path = os.path.relpath(file_path, source_directory)
            dest_file_path = os.path.join(destination_directory, 'uncategorized', rel_path)
            os.makedirs(os.path.dirname(dest_file_path), exist_ok=True)
            shutil.copy(file_path, dest_file_path)

print("Copying files based on EXIF data with source directory name is complete.")