OSX Photos, Applescript: loop through Moments?

2019-07-11 05:43发布

问题:

I am very new to AppleScript but have worked extensively (for years) with other scripting languages, so not entirely new to the game. I have just sadly said goodbye to Aperture and imported my nearly 100K digital images into Photos (so I'm also brand new to Photos). I would like to make a sane structure for finding images, i.e.

Folders named for Year (e.g. 2004)
contain Folders named for Month (e.g. 05)
contain Albums named for each day for which there are images (e.g. 2004-05-03)
(yes this is basically the Picasa convention, which I am accustomed to and like)

Having imported my 100K images into Photos, apparently with success, I find that they are organised by default into "Moments" (i.e. dates), but there is no hierarchical organisation to make browsing easier, as above. So I would like to write an AppleScript to do as follows:

foreach Moment
   parse the date and create folder for year if it does not exist already
   create folder inside year for month if not exists already
   create album inside month for day, if not exists already
   assign all photos in this Moment to that album

Seems simple enough, and it would take tens of hours by hand :-) so never going to happen unless I can script it. I've been reading the (seemingly rather limited) AppleScript dictionary for Photos and so far have not seen any useful reference to Moments, as in how to loop through a list of them all, find list of images contained in one, etc. I see the object "moment" defined with two attributes, ID and name; but I'm floundering around a bit trying to find the master list of all Moments or the contents of Moments.

I have a feeling that 2 paragraphs or one chunk of sample code from someone familiar with this app (and with AppleScript) would save me hours of googling. Does anyone know how to go about this?

[update]

I have tried DLing and installing a promising script library for Photos

https://photosautomation.com/scripting/script-library.html

but so far have not been able to get any of its functions to execute. I have also tried the most basic exploratory command to Photos:

tell application "Photos"
    activate
    set moms to the moments of application
    display dialog moms
end tell

and got a not-too-enlightening error message:

error "Can’t get every moment of application." number -1728 from every «class IPmm» of application

回答1:

I wrote this on Yosemite (10.10.5) for Photos 1.0.1 so it may need some modifications for you, but it's the best I could do, hopefully it will work on your OS. I tried to comment it for you so you'd be able to see what it was doing.

on run
    tell application "Photos"
        set mediaItems to every media item
        repeat with mediaItem in mediaItems
            set mdate to (date of mediaItem) -- get the date of the file
            set yearName to year of mdate as string -- year of the file
            set YrFolder to my yearFolder(yearName) -- make the year folder

            set mmonth to month of mdate -- month of the file
            set monthName to my monthNum(mmonth as string) -- month name as a number
            set SubFold to my subFolder(monthName, YrFolder) -- make the month number folder

            set mday to day of mdate -- day of the file
            set dayName to my dayNum(mday as string) -- get the day as a two digit number
            set albumName to yearName & "-" & monthName & "-" & dayName as string -- create the album name
            set finalAlbum to my makeAlbum(albumName, SubFold) -- make the album

            add {mediaItem} to finalAlbum -- put the item in the album
        end repeat
    end tell

end run


on dayNum(mday)
    if (count of characters in mday) = 1 then
        return "0" & mday as string
    else
        return mday as string
    end if
end dayNum

on monthNum(mmonth)
    if mmonth = "January" then
        set num to "01"
    else if mmonth = "February" then
        set num to "02"
    else if mmonth = "March" then
        set num to "03"
    else if mmonth = "April" then
        set num to "04"
    else if mmonth = "May" then
        set num to "05"
    else if mmonth = "June" then
        set num to "06"
    else if mmonth = "July" then
        set num to "07"
    else if mmonth = "August" then
        set num to "08"
    else if mmonth = "September" then
        set num to "09"
    else if mmonth = "October" then
        set num to "10"
    else if mmonth = "November" then
        set num to "11"
    else if mmonth = "December" then
        set num to "12"
    end if
    return num
end monthNum


on makeAlbum(albName, theFolder)
    tell application "Photos"
        set yrFold to name of parent of theFolder
        if exists container albName of container (name of theFolder) of container yrFold then
            return (container albName of container (name of theFolder) of container yrFold)
        else
            return make new album named albName at theFolder
        end if
    end tell
end makeAlbum


on subFolder(subName, YrFolder)
    tell application "Photos"
        if exists container subName of container (name of YrFolder) then
            return container subName of container (name of YrFolder)
        else
            return make new folder named subName at YrFolder
        end if
    end tell
end subFolder

on yearFolder(yearName)
    tell application "Photos"
        if container named yearName exists then
            return container named yearName
        else
            try
                return make new folder named yearName
            on error
                return ""
            end try
        end if
    end tell
end yearFolder

Best of luck with it, would love to know if it works for you.



回答2:

Current working version

Code is now too long to post here, but thanks for the starting point! it's running even now -- painfully slowly, of course, but seems to be working. There are over 97K images in my Photos library so this could take days. [update: 10000 images every 2 hours, so about 18 hours] AS syntax still strikes me as decidedly odd :-) but thanks to your sample code I could whack this together PDQ and, I hope, solve the problem.

[update] YES, it worked. about 20 hrs run time, zero errors, and looks like success. thanks very much for the code sample. problem solved.