Skip to content

Instantly share code, notes, and snippets.

@ArnyminerZ
Last active September 15, 2024 10:01
Show Gist options
  • Save ArnyminerZ/93e12b9490d4b358ba9ef54932e39e8e to your computer and use it in GitHub Desktop.
Save ArnyminerZ/93e12b9490d4b358ba9ef54932e39e8e to your computer and use it in GitHub Desktop.
Sort all the files inside a directory by extracting its creation date. Intended to be used with photos.

Requirements

pip install exifread

Usage

Replace path_to_sort by the path where all the photos are stored at

import os
import shutil
import datetime
import exifread
def sort_files_by_date(path):
"""Sorts files within folders by capture date, then last modification date, then creation date.
Args:
path: The path to the directory containing the files.
"""
for root, dirs, files in os.walk(path):
for file in files:
file_path = os.path.join(root, file)
try:
# Attempt to get the capture date from metadata
capture_date = get_capture_date_from_metadata(file_path)
if capture_date:
sort_by_date(int(round(capture_date.timestamp())), file_path)
continue
except Exception as e:
# If metadata fails, try last modification date
print(f"Error getting capture date for {file_path}: {e}")
sort_by_date(os.path.getmtime(file_path), file_path)
def get_capture_date_from_metadata(file_path) -> datetime.datetime|None:
"""Extracts the capture date from the file's EXIF metadata.
Args:
file_path: The path to the file.
Returns:
The capture date as a datetime.datetime object, or None if it cannot be extracted.
"""
with open(file_path, 'rb') as f:
tags = exifread.process_file(f)
if 'EXIF DateTimeOriginal' in tags:
capture_date_str = tags['EXIF DateTimeOriginal'].values
try:
capture_date = datetime.datetime.strptime(capture_date_str, '%Y-%m-%d %H:%M:%S')
return capture_date
except:
# Use alternative format
capture_date = datetime.datetime.strptime(capture_date_str, '%Y:%m:%d %H:%M:%S')
return capture_date
return None
def sort_by_date(date, file_path):
"""Moves the file to a new directory based on the given date.
Args:
date: The date as a timestamp.
file_path: The path to the file.
"""
date_time = datetime.datetime.fromtimestamp(date)
year_dir = f"{date_time.year}"
date_dir = f"{date_time.year}-{date_time.month:02d}-{date_time.day:02d}"
new_path = os.path.join(os.path.dirname(file_path), year_dir, date_dir)
os.makedirs(new_path, exist_ok=True)
shutil.move(file_path, os.path.join(new_path, os.path.basename(file_path)))
# Example usage
path_to_sort = "/path/to/photos"
sort_files_by_date(path_to_sort)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment