Skip to content

Instantly share code, notes, and snippets.

@cmbuckley
Last active March 15, 2021 18:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cmbuckley/2c4922f8fdd0725210841dd82bae4ac5 to your computer and use it in GitHub Desktop.
Save cmbuckley/2c4922f8fdd0725210841dd82bae4ac5 to your computer and use it in GitHub Desktop.
tell application "Photos"
activate
set folderList to name of every folder
set selectedFolders to choose from list folderList with prompt "Select folders:" with multiple selections allowed
set destination to POSIX path of (choose folder with prompt "Please select a backup location:")
repeat with f in folders
if selectedFolders contains name of f then
my exportFolder(f, destination)
end if
end repeat
end tell
-- export a folder to a given destination
on exportFolder(tFolder, tPath)
set folderName to tPath & "/" & my getFolderName(tFolder)
log folderName
using terms from application "Photos"
tell tFolder
repeat with childAlbum in albums
my exportAlbum(childAlbum, folderName)
end repeat
repeat with childFolder in folders
my exportFolder(childFolder, folderName)
end repeat
end tell
end using terms from
end exportFolder
-- work out the folder name
on getFolderName(tFolder)
set dateNames to {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}
set folderName to name of tFolder
if dateNames contains folderName then
repeat with idx from 1 to the count of dateNames
if item idx of dateNames is folderName then return text -2 thru -1 of ("0" & idx)
end repeat
end if
return folderName
end getFolderName
-- export an album to a given destination
on exportAlbum(tAlbum, tPath)
set albumName to tPath & "/" & my getAlbumName(tAlbum, tPath)
my makeFolder(albumName)
log albumName
tell application "Photos"
try
with timeout of 30 * 60 seconds
export (get media items of tAlbum) to (albumName as POSIX file) with using originals
end timeout
on error
tell me to delay 5
activate
with timeout of 30 * 60 seconds
export (get media items of tAlbum) to (albumName as POSIX file) with using originals
end timeout
end try
end tell
end exportAlbum
-- get an album name
-- some albums have no date prefix (if they are in Misc folder or are empty)
-- if all the dates are the same, use "YYYY-MM-DD Album"
-- if date is within a month, use "YYYY-MM-DD–EE Album"
-- otherwise use "YYYY-MM-DD–ZZZZ-NN-EE Album"
on getAlbumName(tAlbum, tPath)
using terms from application "Photos"
-- to avoid Photos naming clash there are some with "(2)" or "(1 Apr)", remove this
set albumName to do shell script "sed 's/ ([0-9].*)$//g' <<< " & quoted form of ((name of tAlbum) as text)
if tPath contains "/Misc/" then return albumName
set uniqueDates to {}
set photoDates to date of every media item of tAlbum
if (count of photoDates) = 0 then return albumName -- empty album
repeat with photoDate in photoDates
set [d, m, y] to [day, month, year] of photoDate
set m to m * 1
set m to text -1 thru -2 of ("0" & m)
set d to text -1 thru -2 of ("0" & d)
set the text item delimiters to "-"
set newDate to {y, m, d} as string
if uniqueDates does not contain newDate then set end of uniqueDates to newDate
end repeat
-- single date
if length of uniqueDates = 1 then return first item of uniqueDates & " " & albumName
set sortedDates to my sortList(uniqueDates)
set minDate to first item of sortedDates
set maxDate to last item of sortedDates
-- same month
if text 1 thru 7 of minDate = text 1 thru 7 of maxDate then
return minDate & "–" & text 9 thru end of maxDate & " " & albumName
end if
-- different month/year
return minDate & "–" & maxDate & " " & albumName
end using terms from
end getAlbumName
on makeFolder(tPath)
do shell script "mkdir -p " & quoted form of tPath
end makeFolder
-- from: https://developer.apple.com/library/content/documentation/LanguagesUtilities/Conceptual/MacAutomationScriptingGuide/ManipulateListsofItems.html
on sortList(theList)
set theIndexList to {}
set theSortedList to {}
try
repeat (length of theList) times
set theLowItem to ""
repeat with a from 1 to (length of theList)
if a is not in theIndexList then
set theCurrentItem to item a of theList as text
if theLowItem is "" then
set theLowItem to theCurrentItem
set theLowItemIndex to a
else if theCurrentItem comes before theLowItem then
set theLowItem to theCurrentItem
set theLowItemIndex to a
end if
end if
end repeat
set end of theSortedList to theLowItem
set end of theIndexList to theLowItemIndex
end repeat
on error errMsg number errorNumber
return {"An unknown error occurred:"} & theSortedList
end try
return theSortedList
end sortList
@cmbuckley
Copy link
Author

Script to recursively export albums from Photos.

Starting with an album structure like:

2011
  Jan
    Album 1
    Album 2
  Feb
    Album 3

and converting to a similar folder structure:

2011/
  01/
    2011-01-01 Album 1/
    2011-01-05–06 Album 2/
  02/
    2011-02-28–2011-03-01 Album 3/

Where the date ranges depend on the creation dates of the media items within.

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