Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

RedTrenches

macrumors newbie
Original poster
Aug 11, 2024
3
1
I’m hoping someone here can help me with a bit of a tricky situation I’m facing with my Apple Photos library. During the import process, the date and time metadata for my photos got all messed up. The good news is that the correct date and time are encoded in the filenames of the photos.

Here’s the catch: I don’t have enough space on my SSD to export and re-import the photos, so I need to find a way to fix this directly within Apple Photos. I’ve heard that Automator and AppleScript might be able to help, but I’m not very experienced with scripting.

What I’m looking for is a way to automate the process of reading the date and time from the filenames and updating the metadata of the photos in Apple Photos. If anyone has scripts, tools, or plugins that could help me achieve this without needing to export the photos, that would be amazing.

Any step-by-step guidance or examples of similar scripts that I can adapt to my needs would be incredibly helpful. I really appreciate any advice or pointers you can provide.
 

NoBoMac

Moderator
Staff member
Jul 1, 2014
6,302
5,021
During the import process, the date and time metadata for my photos got all messed up.

Are you looking at Imports on the sidebar? Might (probably?) not be messed up.

The images under Imports will be listed by import date vs if you go to Library, images will be listed by metadata date.

For example, under Imports, first image under it:

Screenshot 2024-08-11 at 2.09.12 PM.png

But under Library, same image, listed "correctly":

Screenshot 2024-08-11 at 2.10.54 PM.png
 
  • Like
Reactions: splifingate

RhetTbull

macrumors member
Apr 18, 2022
99
73
Los Angeles, CA
I’m hoping someone here can help me with a bit of a tricky situation I’m facing with my Apple Photos library. During the import process, the date and time metadata for my photos got all messed up. The good news is that the correct date and time are encoded in the filenames of the photos.

Here’s the catch: I don’t have enough space on my SSD to export and re-import the photos, so I need to find a way to fix this directly within Apple Photos. I’ve heard that Automator and AppleScript might be able to help, but I’m not very experienced with scripting.

What I’m looking for is a way to automate the process of reading the date and time from the filenames and updating the metadata of the photos in Apple Photos. If anyone has scripts, tools, or plugins that could help me achieve this without needing to export the photos, that would be amazing.

Any step-by-step guidance or examples of similar scripts that I can adapt to my needs would be incredibly helpful. I really appreciate any advice or pointers you can provide.
I'm the author of a free open source tool, osxphotos that provides several utilities for working with photos (import, export, etc) and one of these is the "osxphotos timewarp" utility which will do exactly what you're asking.

To do this, you would use the "osxphotos timewarp --parse-date PATTERN" option to parse the date from the file.

If your photos are named 'IMG_1234_2022_11_23_12_34_56.jpg' where the
date/time is '2022-11-23 12:34:56', you could use the pattern '%Y_%m_%d_%H_%M_%S' or 'IMG_*_%Y_%m_%d_%H_%M_%S'

The argument to --parse-date is a pattern string that is used to parse the date/time from the filename. The pattern string is a superset of the python strftime/strptime format with the following additions:

• *: Match any number of characters
• ^: Match the beginning of the string
• $: Match the end of the string
• {n}: Match exactly n characters
• {n,}: Match at least n characters
• {n,m}: Match at least n characters and at most m characters
• In addition to %% for a literal %, the following format codes are supported: %^, %$, %*, %|, %{, %} for ^,
$, *, |, {, } respectively
• |: join multiple format codes; each code is tried in order until one matches
• Unlike the standard library, the leading zero is not optional for %d, %m, %H, %I, %M, %S, %j, %U, %W, and
%V
• For optional leading zero, use %-d, %-m, %-H, %-I, %-M, %-S, %-j, %-U, %-W, and %-V

For more information on strptime format codes, see: https://docs.python.org/3/library/datetime.html?strptime#strftime-and-strptime-format-codes

If you provide me some example filenames I can help further refine the pattern for you.

To use timewarp, you need to first install osxphotos using these instructions: https://github.com/RhetTbull/osxphotos?tab=readme-ov-file#installation

Then, select a few photos in the Photos library view or in an album (selecting in a Smart Album will not work) and in the Terminal, run the command:

osxphotos timewarp --verbose --parse-date "%Y_%m_%d_%H_%M_%S"

(this assumes your file is in the format used in the example above)

If everything works as expected, select the rest of the affected files and run the command again.
 

RedTrenches

macrumors newbie
Original poster
Aug 11, 2024
3
1
I'm the author of a free open source tool, osxphotos that provides several utilities for working with photos (import, export, etc) and one of these is the "osxphotos timewarp" utility which will do exactly what you're asking.

To do this, you would use the "osxphotos timewarp --parse-date PATTERN" option to parse the date from the file.

If your photos are named 'IMG_1234_2022_11_23_12_34_56.jpg' where the
date/time is '2022-11-23 12:34:56', you could use the pattern '%Y_%m_%d_%H_%M_%S' or 'IMG_*_%Y_%m_%d_%H_%M_%S'

The argument to --parse-date is a pattern string that is used to parse the date/time from the filename. The pattern string is a superset of the python strftime/strptime format with the following additions:

• *: Match any number of characters
• ^: Match the beginning of the string
• $: Match the end of the string
• {n}: Match exactly n characters
• {n,}: Match at least n characters
• {n,m}: Match at least n characters and at most m characters
• In addition to %% for a literal %, the following format codes are supported: %^, %$, %*, %|, %{, %} for ^,
$, *, |, {, } respectively
• |: join multiple format codes; each code is tried in order until one matches
• Unlike the standard library, the leading zero is not optional for %d, %m, %H, %I, %M, %S, %j, %U, %W, and
%V
• For optional leading zero, use %-d, %-m, %-H, %-I, %-M, %-S, %-j, %-U, %-W, and %-V

For more information on strptime format codes, see: https://docs.python.org/3/library/datetime.html?strptime#strftime-and-strptime-format-codes

If you provide me some example filenames I can help further refine the pattern for you.

To use timewarp, you need to first install osxphotos using these instructions: https://github.com/RhetTbull/osxphotos?tab=readme-ov-file#installation

Then, select a few photos in the Photos library view or in an album (selecting in a Smart Album will not work) and in the Terminal, run the command:

osxphotos timewarp --verbose --parse-date "%Y_%m_%d_%H_%M_%S"

(this assumes your file is in the format used in the example above)

If everything works as expected, select the rest of the affected files and run the command again.
Thank you, it seems exactly what I need :)

I have successfully installed the osxphotos on my Mac Sonoma 14.6.1 from your online instructions.
I have then identified the following three filenames patterns which have date issue in my library:
  • IMG-20230418-WA0002.jpg
  • signal-2023-04-16-14-12-33-364.jpg
  • VID-20220125-WA0002.mp4
I need to:
  1. Look for all the photos in my whole Photos Library matching these filename patterns.
  2. Change their date accordingly.
  3. Save an output file with the list of changed photos (filename, old date, new date).
As I am not the best Python user (I only have very basic knowledge in programming language), I tried to ask support to ChatGPT. The generated code was the following:

Python:
import osxphotos
import re
import os
from datetime import datetime
from tqdm import tqdm  # Import the tqdm library for the progress bar

# Define the patterns for the filenames
patterns = [
    (r"IMG-(\d{4})(\d{2})(\d{2})-WA\d{4}\.jpg", "%Y%m%d"),  # For IMG-20230418-WA0002.jpg
    (r"signal-(\d{4})-(\d{2})-(\d{2})-\d{2}-\d{2}-\d{2}-\d{3}\.jpg", "%Y-%m-%d"),  # For signal-2023-04-16-14-12-33-364.jpg
    (r"VID-(\d{4})(\d{2})(\d{2})-WA\d{4}\.mp4", "%Y%m%d")  # For VID-20220125-WA0002.mp4
]

# Initialize osxphotos
photosdb = osxphotos.PhotosDB()

# Prepare a list to store the changes
changed_photos = []

# Get the total number of photos in the library
total_photos = len(photosdb.photos())

# Loop through all photos in the library with a progress bar
for photo in tqdm(photosdb.photos(), desc="Processing photos", total=total_photos):
    for pattern, date_format in patterns:
        match = photo.original_filename and re.match(pattern, photo.original_filename)
        if match:
            # Extract the date components from the filename
            date_str = "".join(match.groups())
           
            try:
                new_date = datetime.strptime(date_str, date_format).date()
            except ValueError:
                print(f"Skipping {photo.original_filename}: date format mismatch")
                continue
           
            # Save the old date before changing
            old_date = photo.date.date()
           
            if new_date != old_date:
                # Update the photo's date
                photo.set_date(new_date)

                # Add the change to our list
                changed_photos.append((photo.original_filename, old_date, new_date))

# Print the results
for filename, old_date, new_date in changed_photos:
    print(f"{filename}: {old_date} -> {new_date}")

# Save the changes to a CSV file on the desktop
output_file = os.path.expanduser("~/Desktop/photo_date_changes.csv")
with open(output_file, "w") as f:
    f.write("Filename,Old Date,New Date\n")
    for filename, old_date, new_date in changed_photos:
        f.write(f"{filename},{old_date},{new_date}\n")

print(f"List of changed photos saved to {output_file}")

However, I get the following error when I run it:
Code:
line 42, in <module>
    photo.set_date(new_date)
    ^^^^^^^^^^^^^^
AttributeError: 'PhotoInfo' object has no attribute 'set_date'

And, according with ChatGPT:
Unfortunately, the osxphotos library currently does not support directly modifying the metadata of existing photos.

Any advice here?
 

RhetTbull

macrumors member
Apr 18, 2022
99
73
Los Angeles, CA
Any advice here?
Although OSXPhotos is written in python and can be used as a python library to create your own scripts, you should not need to write any code to use it to accomplish what you want. OSXPhotos provides a number of very flexible command line tools that should do the trick. The one exception is that the report generation cannot be done automatically but you can get close. I'm not going to bother commenting on the ChatGPT generated code as I find that with custom libraries like OSXPhotos that aren't in common use, it just makes stuff up. There are also a number of nuances that would need to be considered when modifying the library. But as I said, OSXPhotos can do this without writing custom python.

First, let's collect all the assets in the library that match these patterns:

- IMG-20230418-WA0002.jpg
- signal-2023-04-16-14-12-33-364.jpg
- VID-20220125-WA0002.mp4

I'm assuming that in the first and third case, the format is XXX-YYYYMMDD-XXNNNN where X is any character and N is any number. Does the last part always being with WA? For now I'll assume it does but we can adjust this if needed.

I'm assuming in the second case, the format is X*-YYYY-MM-DD-HH-MM-SS-FFF where FFF is fractional seconds (milliseconds or microseconds) and X* means "any number of letters". In the examples below I will ignore the FFF part as I don't know what that specifies. It looks like milliseconds but date/time conventions typically specify microseconds and the date parsing library OSXPhotos uses only handles microseconds.

The following OSXPhotos command can be run from the command line to find these and add them to the album "Fix dates":

osxphotos query --query-eval "re.match(r'^\w+-(\d{8}-WA\d+|\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2})', photo.original_filename)" --field uuid {uuid} --field filename {photo.original_filename} --field date {photo.date} --add-to-album "Fix dates"

This uses the `osxphotos query` command to run a query to find all photos matching your pattern, outputs a report in CSV format with the ID, filename, and current date for each photo, and adds them to the album "Fix dates" which will be created if necessary. I lied...you need a tiny bit of python to do the pattern matching; `--query-eval` runs a line of python code against the photos to find the matching photos. There are many other query options that don't require using any code but to find these specific patterns, we needed to resort to a python regular expression.

To save the report as a CSV file, you'd add `> report_before.csv` to the command:

osxphotos query --query-eval "re.match(r'^\w+-(\d{8}-WA\d+|\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2})', photo.original_filename)" --field uuid {uuid} --field filename {photo.original_filename} --field date {photo.date} --add-to-album "Fix dates" > report_before.csv

Once you have all those photos, you can open the album, select them (I'd start with a small subset), then run the following command to change the dates:

osxphotos timewarp --parse-date "^*-%Y-%m-%d-%H-%M-%S*|*-%Y%m%d-WA*" --verbose

Unlike most other OSXPhotos commands, timewarp does not have a `--dry-run` option to preview the changes nor does it generate a report. Using `--verbose` will show you what it's doing. I have open issues to add both reporting and dry run mode to timewarp in the future. I suggest you start with a couple of the images collected in the first step to ensure timewarp is working as expected then run the command on all the rest. The timewarp command only processes photos you have selected in Photos so you can easily open the album created in step 1 and select all or a subset of the photos then run the command.

To generate the "after processing" report, you can re-run the query command. Select the photos you changed then run this command:

osxphotos query --selected --field uuid {uuid} --field filename {photo.original_filename} --field date {photo.date} > report_after.csv

You'll now have two CSV reports with the UUID (unique to each photo), the filename, and the date/time. For this task, I'm certain ChatGPT could help you with a simple python script that would read the two files and created a combined report that shows both dates. You could also open them in Excel or Google Sheets and sort on UUID then combine the data.
 

RedTrenches

macrumors newbie
Original poster
Aug 11, 2024
3
1
Although OSXPhotos is written in python and can be used as a python library to create your own scripts, you should not need to write any code to use it to accomplish what you want. OSXPhotos provides a number of very flexible command line tools that should do the trick. The one exception is that the report generation cannot be done automatically but you can get close. I'm not going to bother commenting on the ChatGPT generated code as I find that with custom libraries like OSXPhotos that aren't in common use, it just makes stuff up. There are also a number of nuances that would need to be considered when modifying the library. But as I said, OSXPhotos can do this without writing custom python.

First, let's collect all the assets in the library that match these patterns:

- IMG-20230418-WA0002.jpg
- signal-2023-04-16-14-12-33-364.jpg
- VID-20220125-WA0002.mp4

I'm assuming that in the first and third case, the format is XXX-YYYYMMDD-XXNNNN where X is any character and N is any number. Does the last part always being with WA? For now I'll assume it does but we can adjust this if needed.

I'm assuming in the second case, the format is X*-YYYY-MM-DD-HH-MM-SS-FFF where FFF is fractional seconds (milliseconds or microseconds) and X* means "any number of letters". In the examples below I will ignore the FFF part as I don't know what that specifies. It looks like milliseconds but date/time conventions typically specify microseconds and the date parsing library OSXPhotos uses only handles microseconds.

The following OSXPhotos command can be run from the command line to find these and add them to the album "Fix dates":

osxphotos query --query-eval "re.match(r'^\w+-(\d{8}-WA\d+|\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2})', photo.original_filename)" --field uuid {uuid} --field filename {photo.original_filename} --field date {photo.date} --add-to-album "Fix dates"

This uses the `osxphotos query` command to run a query to find all photos matching your pattern, outputs a report in CSV format with the ID, filename, and current date for each photo, and adds them to the album "Fix dates" which will be created if necessary. I lied...you need a tiny bit of python to do the pattern matching; `--query-eval` runs a line of python code against the photos to find the matching photos. There are many other query options that don't require using any code but to find these specific patterns, we needed to resort to a python regular expression.

To save the report as a CSV file, you'd add `> report_before.csv` to the command:

osxphotos query --query-eval "re.match(r'^\w+-(\d{8}-WA\d+|\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2})', photo.original_filename)" --field uuid {uuid} --field filename {photo.original_filename} --field date {photo.date} --add-to-album "Fix dates" > report_before.csv

Once you have all those photos, you can open the album, select them (I'd start with a small subset), then run the following command to change the dates:

osxphotos timewarp --parse-date "^*-%Y-%m-%d-%H-%M-%S*|*-%Y%m%d-WA*" --verbose

Unlike most other OSXPhotos commands, timewarp does not have a `--dry-run` option to preview the changes nor does it generate a report. Using `--verbose` will show you what it's doing. I have open issues to add both reporting and dry run mode to timewarp in the future. I suggest you start with a couple of the images collected in the first step to ensure timewarp is working as expected then run the command on all the rest. The timewarp command only processes photos you have selected in Photos so you can easily open the album created in step 1 and select all or a subset of the photos then run the command.

To generate the "after processing" report, you can re-run the query command. Select the photos you changed then run this command:

osxphotos query --selected --field uuid {uuid} --field filename {photo.original_filename} --field date {photo.date} > report_after.csv

You'll now have two CSV reports with the UUID (unique to each photo), the filename, and the date/time. For this task, I'm certain ChatGPT could help you with a simple python script that would read the two files and created a combined report that shows both dates. You could also open them in Excel or Google Sheets and sort on UUID then combine the data.

I cannot thank you enough... Your steps worked without any issues and saved me hours of manual date adjustment... Indeed it is incredible that you can fix the dates with only two lines, what a powerful tool you have developed!

Just for info, here the small python script that merges the two csv files, written by ChatGPT as advised 😆

Python:
import pandas as pd

# Load the CSV files
report_before = pd.read_csv("~/Desktop/report_before.csv")
report_after = pd.read_csv("~/Desktop/report_after.csv")

# Updating the comparison script to use UUID for matching

# Merging 'report_before' and 'report_after' on 'uuid' to compare old and new dates
merged_report = pd.merge(report_before, report_after, on='uuid', suffixes=('_before', '_after'))

# Selecting relevant columns for the final comparison report
comparison_report = merged_report[['filename_before', 'date_before', 'date_after']]
comparison_report.columns = ['Filename', 'Old Date', 'New Date']

# Save the comparison report to a CSV file on the Desktop
comparison_report.to_csv("~/Desktop/comparison_report.csv", index=False)

comparison_report.head()

print("Comparison report generated and saved as 'comparison_report.csv' on your Desktop.")
Screenshot.png



Thanks again for your time and your excellent tool!
 
Last edited:
  • Like
Reactions: RhetTbull
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.