Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
macOS Automator script to rename photos/videos based on creation date. Blog post: https://paulgalow.com/macos-quick-action-rename-photos-videos-timestamp
#!/bin/bash
# macOS Automator script to rename photos/videos based on creation date
# Blog post: https://paulgalow.com/macos-quick-action-rename-photos-videos-timestamp
export PATH=/usr/bin:/bin:/usr/sbin:/sbin
# Create subfolder to store renamed files
createDestination() {
readonly destination="$(dirname "$file")/sorted"
mkdir -p "$destination"
}
# Check for file MIME type
hasMIMEType() {
file -I "$file" | grep -q "$1"
}
# Send notification to user
sendNotification() {
osascript <<-EndOfMessage
display notification \
"$1" \
with title "Rename (Timestamp)"
EndOfMessage
}
# Determine file extension
setFileExtension() {
if hasMIMEType "image/jpeg"
then
extension="jpg"
elif hasMIMEType "video/quicktime"
then
extension="mov"
else
return 1
fi
}
# Retrieve EXIF timestamp from media file
getTimeStamp() {
local -r timestampRaw=$(mdls -name kMDItemContentCreationDate -raw "$file" | cut -d ' ' -f -2)
timestamp=${timestampRaw//:/-}
}
# Rename file, handle timestamp collisions
renameFile() {
# Exit function if file type is not supported
setFileExtension || return 0
getTimeStamp || return 0
createDestination || return 1
# Check if to be renamed file already exists
if [[ -f "$destination/$timestamp.$extension" ]]
then
# If file exists append random string to file
local -r randomString=$(md5 -q "$file")
cp "$file" "$destination/$timestamp-$randomString.$extension"
else
cp "$file" "$destination/$timestamp.$extension"
fi
}
# Send notification to user after the process has finished
presentResults() {
# Count files in destination folder
local counter=0
for file in "$destination"/*.*
do
(( counter ++ ))
done
# Check if renaming was successful
if [ $counter != 0 ] && [ -n "$destination" ]
then
sendNotification "$counter photos/videos have been renamed. Opening destination folder…"
open "$destination"
else
sendNotification "Could not renamd any photos/videos."
fi
}
# Main loop to collect input files from Automator
processFiles() {
while read -r file; do
renameFile
done
}
sendNotification "Processing photos/videos.\\nThis can take a while…"
processFiles
presentResults
exit 0
@paulgalow
Copy link
Author

paulgalow commented Apr 15, 2020

mdls has an option for printing only a specific attribute's value: mdls -name kMDItemContentCreationDate -raw <filename>

Thanks for pointing me to this, @alisey. I have updated the gist after your suggestion. And sorry for my late reply. I somehow managed to completely miss your comment.

@Minagamb
Copy link

Minagamb commented Oct 2, 2020

Hi, I am using your code, but there seems to be an error. The timestamp after the photo is renamed does not correlate with the actual time stamp on the photo. For instance, a photo was renamed to 2020-07-03 18 01 07.jpg, but the actual timestamp is at 11:01 am, not 6:01 pm. Everything else is correct except for the time. Also, how can I get rid of the dashes on the date? All the renamed dates are off by 7 hours too much.

@paulgalow
Copy link
Author

paulgalow commented Oct 2, 2020

Hi @Minagamb, the resulting timestamps are UTC based so perhaps that explains why your timestamps are 7 hours off. Regarding the dashes on the date, try replacing timestamp=${timestampRaw//:/-} with timestamp=${timestampRaw//[:|-]/}.

@Minagamb
Copy link

Minagamb commented Oct 2, 2020

how do I change from UTC? The photos are collected PST

@Minagamb
Copy link

Minagamb commented Oct 2, 2020

Also thank you for getting rid of the dashes!

@Minagamb
Copy link

Minagamb commented Oct 2, 2020

how can I convert from UTC to my local time zone? or can I just subtract the 7 hours into the script so that each file has 7 hours subtracted from it? Sorry for bombarding you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment