pip install exifread
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) |