Search code examples
applescriptiphoto

AppleScript Syntax for iPhoto Automation


I've been looking around via Google for some pointers to get me going on something I need to do in iPhoto via AppleScript, but so far haven't found a whole lot. There are various old discussions of scripts for various old versions of iPhoto floating around, but nothing that's been particularly helpful with what I need. Basically, in pseudo-code, I'm looking to do this:

for each photo in library
  if photo.Description contains "a known string"
    photo.Description = photo.Description.Replace("a known string", "")
  end if
end for

That is, I have a piece of errant text which has made its way into every (well, nearly every) photo in my library. I'm guessing I botched up a batch change at some point in the past and didn't notice it until now. Either that or the upgrade from iPhoto '08 to '11 did it somehow. Either way, the net result is the same.

I'm not well-versed in AppleScript, and am having trouble just finding the right syntax/vocabulary to use in this. Basically, I'm at the tell application "iPhoto" part, but don't know what to tell it. If the hierarchy of how photos in the library are organized is important:

  1. Every photo is organized chronologically into events. (Events are my primary form of organization.)
  2. There are a good number of albums, but not everything is in an album.
  3. There is a single smart album which contains every errant photo. This is, of course, based on the presence of the known string in the photo description. So I suppose that may need to be kept in mind if the final code loops through photos in this smart album, since the smart album may be changing the array being iterated over, no?

Does anybody have any references or sample code to help get me going? Conversely, does anybody know of a better way to do this one-time mass fix?

Edit: I ran a test with the following code:

tell application "iPhoto"
    activate
    set thePhotos to get every photo
    repeat with aPhoto in thePhotos
        if aPhoto's comment contains "[known string]" then
            log aPhoto's comment
            tell aPhoto to set it's comment to text 1 thru (offset of "[known string]" in aPhoto's comment) of aPhoto's comment
            log aPhoto's comment
            exit repeat
        end if
    end repeat
end tell

Which resulted in the following output:

tell application "iPhoto"
    activate
    get every photo
    get comment of photo id 4.294977224E+9
    (*comment of photo id 4.294977224E+9*)
    offset of "[known string]" in comment of photo id 4.294977224E+9
    «event ascrgdut»
    offset of "[known string]" in comment of photo id 4.294977224E+9
end tell
tell current application
    offset of "[known string]" in «class pcom» of «class ipmr» id 4.294977224E+9
Result:
error "iPhoto got an error: Can’t make comment of photo id 4.294977224E+9 into type string." number -1700 from comment of photo id 4.294977224E+9 to string

Edit: I had some time to tinker with it this morning and it looks like some type casting was all that was needed. This code is now successfully changing the first matching photo it finds:

tell application "iPhoto"
    activate
    set thePhotos to get every photo
    repeat with aPhoto in thePhotos
        if aPhoto's comment contains "[known string]" then
            log aPhoto's comment as text
            set theComment to aPhoto's comment as text
            set theComment to text 1 thru (offset of "[known string]" in theComment) of theComment
            tell aPhoto to set it's comment to theComment
            log aPhoto's comment as text
            exit repeat
        end if
    end repeat
end tell

Now to back up my library and remove the exit repeat. And probably go do something else for a while as it runs :)


Solution

  • Here's a 'brute force' version. This will loop through every photo. You could make this more elegant by restricting to certain albums if you wanted.

    tell application "iPhoto"
        set thePhotos to get every photo
        repeat with aPhoto in thePhotos
            if aPhoto's comment contains "theString" then
                tell aPhoto to set it's comment to "newString"
            end if
        end repeat
    end tell