Pragmatism in the real world

Folder types in AppleScript

I’ve recently moved to Adobe Lightroom Classic for photo editing, but am still using Apple Photos for viewing my photos on my iPhone and iPad. As such, I wanted an easy way to import photos exported from Lightroom into Photos, so I turned to AppleScript.

My requirements are that I want to import all the photos in each sub-folder of a root folder called “ToPhotos” into Folders and Albums in Photos that are a child of the Photos folder “LR”. The fundamentals of this have been solved by ImportPhotoFolders, so all I needed to do was tweak.

Programatically retrieving a list of folders

The key thing to change is that ImportPhotoFolders asks the user to select a list of folders and then iterates over it:

set folderList to (choose folder with multiple selections allowed)
repeat with baseFolder in folderList
    importEachSubFolder(baseFolder, null)
end repeat

As I know the root folder, I don’t want to keep selecting it and can start a the next level down with a list of the folders in the “ToPhotos” folder:

set rootFolder to "Macintosh HD:Users:rob:Pictures:ToPhotos" as alias
tell application "System Events" to set folders_list to folders in rootFolder

repeat with theFolder in folderList
    importEachSubFolder(theFolder, null)
end repeat

This gives a list of folders, but they aren’t the same type as the list from choose folder and so the script errors with a type mismatch when attempting to list the image files in the leaf folders.

The opacity of AppleScript around types is one of the two main troubles I have with the language. (The other is the pseudo-English structured language is remarkably sensitive to implicit English grammar.)

My initial thought was to add:

set baseFolder to (baseFolder as alias)

into the the repeat loop, but that doesn’t work as AppleScript cannot convert a folder of class cfol to an alias.

It turns out that I needed to use Finder, not System Events to do this:

set rootFolder to "Macintosh HD:Users:rob:Pictures:ToPhotos" as alias
tell application "Finder" to set folderList to every folder of rootFolder

repeat with theFolder in folderList
    set baseFolder to (baseFolder as alias)
    importEachSubFolder(theFolder, null)
end repeat

This works because the list of folders returned by Finder are of the class folder, which can be cast to alias!

I suspect that I could have worked with the list of cfol folders from System Events if I had rewritten the rest of the script, but that seemed like too much work.

So now you know. A list of folders is not necessarily a list of folders when it comes to AppleScript…

Finding a folder in Photos

The second thing I wanted to change was to store all my imported folders and albums inside a top-level folder called “LR”.

The second parameter to importEachSubFolder() is the parent folder in Photos, so I just needed to seed it. My first attempted was:

    importEachSubFolder(theFolder, "LR")

Again, this did not work – I don’t have a great track record of getting things right first time with AppleScript! The rest of the script assumes that the parent folder is a Photos folder object and clearly "LR" is a string.

This one is easy to resolve:

tell application "Photos" to set parentFolder to folder "LR"
repeat with theFolder in folderList
    set baseFolder to (baseFolder as alias)
    importEachSubFolder(theFolder, parentFolder)
end repeat

Success

I have now successfully automated importing photos edited in Lightroom into Apple Photos.

In the longer term, I’m hopeful that the new Lightroom “cloud-aware” application will catch up with Lightroom Classic in functionality and this hack will no longer be needed.