Sunday, 20 June 2010

IPhoto Script to Remove Missing Photos

For some reason when you try to open photos you get a big exclamation mark! This seems to happen when the actual photo is missing. Perhaps it has been deleted through the file system or perhaps iPhoto is confused or perhaps because iPhoto crashed during some operation. Who knows.





I wrote this script to find these 'photos' and to move them to the trash.


tell application "iPhoto"
  set curPhotos to selection
  if (count of curPhotos) 0 then
    display alert "You need to select the photos you want me to process."
  else
    set countPhotos to count of items in curPhotos
    repeat with i from 1 to countPhotos
      set thisPhoto to item i of curPhotos
      try
        set t to info for (image path of thisPhoto as POSIX file)
      on error eStr number eNum partial result rList from badObj to expectedType
        log eStr
        select thisPhoto
        remove thisPhoto
      end try
    end repeat
  end if
end tell

Open Script Editor,  cut and paste the above script into the editor, Compile it to check for errors, and save it to a file - perhaps on your desktop but anywhere is fine.

To run it, open iPhoto, select the Photos Library, Select all photos you want to process (Edit - Select All is what I usually do), and then switch back to the Script Editor and press Run.

When it finishes you may have some missing photos in your trash. You can decide what to do with them at this point - I just empty the trash.

If you use it, write a short comment about whether it was helpful or not or whether it worked or not. If you improve the script, let me know as well.

41 comments:

  1. I have been sifting out the web for hours looking for the syntax to build that.
    Here I've just found exactly the solution of my problem
    Soon I'll let you know if it runs properly...
    Thanks in advance!!

    ReplyDelete
  2. I've been using iPhoto lately to organize my "undeleted" photos from a failed drive years ago. Undeleting them resulted in chaotic picture folders lik "Folder12345". A lot of the photos were things I'd gotten from the Internet and screenshots, so I opened the iPhoto library in Finder and manually moved all of the pictures that I didn't want in iPhoto into a different folder.

    I had hoped that iPhoto would be smart enough to purge the links to those removed images automatically, but your script worked perfectly for this. Now I just need to find a way to have iPhoto rename the folders to the Event names or something more descriptive than "Folder12345" (as they were imported that way and have stayed the same).

    Thanks for the script, also if you have any suggestions for how I can rename these folders without losing all of the tagged faces then I would greatly appreciate it!

    ReplyDelete
  3. It's running now. I have almost 19.000 images in iPhoto. It's already running for 20 minutes and 17.430 files left. I'll let it run for the night. Look likes it's working.

    ReplyDelete
  4. This is really one of internet gems.. Thanks a lot

    ReplyDelete
  5. Thanks for the script, this is the only free one I could find.

    Unfortunately, I can't get it to work. I selected some photos of which there were known missing files and it doesn't delete them. In the log it prints the information of only 1 file. I also tried rebuilding the database to no avail. I'm using iPhoto 8.1.2 ('09) and 10.6.6.

    ReplyDelete
  6. Perhaps v8 is different somehow? I have not used it recently and I don't use OS-X much these days after I switched to Ubuntu. Can you post the message in the log?

    ReplyDelete
  7. Sure, here is the log:

    {name:"SB_14954142.jpg", creation date:date "Wednesday, March 23, 2011 9:31:35 PM", modification date:date "Wednesday, March 23, 2011 9:31:35 PM", size:123919, folder:false, alias:false, package folder:false, visible:true, extension hidden:false, name extension:"jpg", displayed name:"SB_14954142.jpg", default application:alias "Macintosh HD:Applications:Preview.app:", kind:"JPEG image", file type:"", file creator:"", type identifier:"public.jpeg", locked:false, busy status:false, short version:"", long version:""}

    In the selection, I had a few that were known to be missing. It mentions "SB_14954142.jpg" which is not missing and is the last picture in the selection.

    In fact, whenever I run it, it always prints the last picture in the selection, whether it is missing or not.

    ReplyDelete
  8. Ok. I actually have v8.

    The script does print out the last selected photo - I don't know why.

    I did this test:

    1. duplicate a photo.
    2. show file
    3. delete photo
    4. empty trash

    Then I selected a few photos in the Events page including the duplicate that I deleted and ran the script.

    The deleted duplicated photo disappeared.

    Try this to confirm it works.

    ReplyDelete
  9. Yeah it still doesn't seem to work. I think the problem is that it is not detecting if the file doesn't exist correctly. I put a display alert into this block of code:


    on error eStr number eNum partial result rList from badObj to expectedType
    display alert "Does not exist"
    log eStr
    select thisPhoto
    remove thisPhoto
    end try

    And the alert never shows up.

    ReplyDelete
  10. I think I found the problem! First, I chose not to have iPhoto import my photos to the iPhoto library and I instead keep them on my external drive.

    So when I select a photo with its original deleted, something strange happens. Rather than return an error, it returns the path to the ALIAS of the file. The alias resides in the normal iPhoto library folder and this file does indeed exist so it does not return an error.

    ReplyDelete
  11. That is great work. So iPhoto makes a link to the file in the other location if you do not want it to copy the photo into it's library.

    I have never used that option.

    Re your penultimate comment, I was going to suggest 'display alert eStr' to see if the script was finding deleted pictures or not - but you worked that out.


    Ok, I did this to test:

    1. I duplicated a photo using Finder (not iPhoto).
    2. I moved it to somewhere else.
    3. I imported it without copying it into the library. iPhoto created an alias as you said.
    4. I deleted the original file.
    5. I emptied the trash.
    6. I selected the imported photo that had just been deleted.
    7. I ran the script. It removed it and put the photo in iPhoto's Trash.

    For me, it seemed to work. I had the 'display alert eStr' line already in there and it mentioned that the original file could not be found - words to that effect.

    ReplyDelete
  12. The displayed message for a photo with an alias where the original file is deleted is this:

    'No result was returned from some part of this expression'

    It was removed and ended in iPhoto's Trash.

    ReplyDelete
  13. Still no luck for me :( They must have changed something in the scripting library for iPhoto '09.

    In the "replies" pane in Applescript, this is what I get when I select a photo that does exist on the external:


    tell application "iPhoto"
    get selection
    --> {photo id 4.294991665E+9}
    get image path of photo id 4.294991665E+9
    --> "/Volumes/My Book/freeagent/3/GWSCAN - Nero1.JPG"
    info for file "My Book:freeagent:3:GWSCAN - Nero1.JPG"
    --> error number -10004
    end tell
    tell current application
    info for file "My Book:freeagent:3:GWSCAN - Nero1.JPG"
    --> {name:"GWSCAN - Nero1.JPG", creation date:date "Wednesday, March 23, 2011 9:31:10 PM", modification date:date "Wednesday, March 23, 2011 9:31:10 PM", size:73525, folder:false, alias:false, package folder:false, visible:true, extension hidden:false, name extension:"JPG", displayed name:"GWSCAN - Nero1.JPG", default application:alias "Macintosh HD:Applications:Preview.app:", kind:"JPEG image", file type:"", file creator:"", type identifier:"public.jpeg", locked:false, busy status:false, short version:"", long version:""}
    end tell


    And this is what happens when I pick one that doesn't exist:

    tell application "iPhoto"
    get selection
    --> {photo id 4.294983806E+9}
    get image path of photo id 4.294983806E+9
    --> "/Users/sciencectn/Pictures/iPhoto Library/Originals/2008/3/GWSCAN - Power2Go4.JPG"
    info for file "Macintosh HD:Users:sciencectn:Pictures:iPhoto Library:Originals:2008:3:GWSCAN - Power2Go4.JPG"
    --> error number -10004
    end tell
    tell current application
    info for file "Macintosh HD:Users:sciencectn:Pictures:iPhoto Library:Originals:2008:3:GWSCAN - Power2Go4.JPG"
    --> {name:"GWSCAN - Power2Go4.JPG", creation date:date "Friday, March 25, 2011 1:07:35 AM", modification date:date "Friday, March 25, 2011 1:07:35 AM", size:656, folder:false, alias:true, package folder:false, visible:true, extension hidden:false, name extension:"JPG", displayed name:"GWSCAN - Power2Go4.JPG", default application:alias "Macintosh HD:Applications:Adobe Fireworks CS5:Adobe Fireworks CS5.app:", kind:"Alias", file type:"", file creator:"", type identifier:"public.jpeg", locked:false, busy status:false, short version:"", long version:""}
    end tell

    I'm pretty terrible at Applescript so I don't know how to fix it. But thanks for all your help, I appreciate it.

    ReplyDelete
  14. Thank you for putting together this script. I would like to use this but is there a way to find these photos and put them in an album instead of the trash?

    The reason is because I have not found a way to drag from the iPhoto trash into an album.

    I need to fix my library, as I have 10's of thousands of these empty pictures.

    ReplyDelete
  15. You could add a comment to the missing photo instead of removing it and then create a smart album where 'any text' is "missing"

    Try replacing
    delete thisPhoto
    with
    set comment of thisPhoto to "missing"

    Run the script on selected photos and then make a smart album as described above.

    You could use whatever comment you like in place of "missing".

    ReplyDelete
  16. Thanks for posting this, it worked exactly as advertised for me

    ReplyDelete
  17. Thanks for commenting.

    sciencectn has had problems with it that I can't replicate, but it seems to have something to do with either mounted drives or alias's.

    ReplyDelete
  18. I have the same error as sciencectn. Shame, because I've been looking for something that does just this.

    iPhoto 8.1.2, OSX 10.6.7

    ReplyDelete
  19. Not sure if this helps, but I had the same problem as sciencectn. My actual photos aren't in the iPhoto Library but on a separate folder (on an external USB drive). I had deleted some of the files purposely using Finder. But the script was not deleting anything in iPhoto because iPhoto seemed to think the files still existed (it seemed to be finding the preview file - just like sciencectn's example above).

    But I simply changed "image path" to "original path" in the script above and it seems to work correctly for me now!

    ReplyDelete
  20. Thanks jasechong, that may be the solution.

    ReplyDelete
  21. it works perfect thks

    ReplyDelete
  22. Thank you so much. This is a very elegant way of doing just what it says it does. Thank you thank you thank you!

    ReplyDelete
  23. Thank you! i was looking for so long for such a script!

    The only thing is: I prefer changing the comment of those missing pictures rather than deleting them directly.
    So this would be my version:

    tell application "iPhoto"
    set curPhotos to selection

    if (count of curPhotos) ≤ 0 then
    display alert "You need to select the photos you want to process."
    else
    set countPhotos to count of items in curPhotos
    repeat with i from 1 to countPhotos
    set thisPhoto to item i of curPhotos
    try
    set picInfo to info for (image path of thisPhoto as POSIX file)
    on error
    set comment of thisPhoto to "Missing"
    end try
    end repeat
    end if

    beep
    display alert "All missing Photos can now be found searching for MISSING!"

    end tell

    ReplyDelete
  24. Really loved this! Very nice job! It really does the trick.
    Thanks again!

    ReplyDelete
  25. I make link to you Blog from this http://www.warinya2u.com/blog/2011/11/mac-%E0%B8%88%E0%B8%B1%E0%B8%94%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%A3%E0%B8%B9%E0%B8%9B%E0%B8%97%E0%B8%B5%E0%B9%88%E0%B8%95%E0%B8%81%E0%B8%84%E0%B9%89%E0%B8%B2%E0%B8%87

    Thank for you article.

    ReplyDelete
  26. Tremendously helpful! I had a few thousand files affected by this.

    Didn't work for me at first. I changed "image path" to "original path". Still didn't work. Then, not knowing what the heck I'm doing, I added the line saying "select t" right after the one where t is set. Not sure why, but it seems some action has to be attempted on t before it can trigger the error. Works great now.

    Ken

    ReplyDelete
  27. Thank you very much! Exactly what i needed to fix my library after upgrading to Lion. Lucky me had all pictures not imported to library, so i could just dnd them back into iPhoto.

    Thanks again!

    ReplyDelete
  28. works like a magic. saved me effort to go look for a new photo app. thanks alot!!

    ReplyDelete
  29. Works like a charm bro, I've been searching the net for a while for a solution to this problem. Thanks a bunch.

    ReplyDelete
  30. IT WORKED !!! THANKS SO MUCH !!!

    ReplyDelete
  31. For me it worked as well!! Thanks for sharing this trick!!!!

    ReplyDelete
  32. Thank you! its stupid Iphoto doesnt do it itself!

    ReplyDelete
  33. Worked well. Just what I needed.

    ReplyDelete
  34. This seems to be working for me, but it got very slow after a while. I have a library with 21,000 photos, so I expect it to take a while, but I do notice lots of -10004 errors. I've read up that it's an administrator privileges error, but what statement could be added after the tell to make sure it has the proper permissions to remove the pictures (to the Trash?)

    ReplyDelete
  35. I'm not going to be able to help here since I switched from OS-X to Linux on all my laptops.

    I still have OS-X installed, but not iPhoto.

    Probably, if it is a permissions problem, you can fix all your photo permissions within Finder and then re-run this script.

    But if it is a permissions problem, how did this happen?

    Your iPhoto library is only accessible by your (or root) and I doubt you would have been using root to modify your iPhoto library.

    ReplyDelete
  36. this works perfectly thank you! My boss thinks I'm a genius. :)

    ReplyDelete
  37. The script works perfectly when used in the "Photos" view. Took me a moment to figure out.

    When selecting images within events or albums it does not as iPhoto returns the list of events or albums with set curPhotos to selection and thus the loop would need to handle all albums and then all photos within I assume. This should be not too hard to fix though if anybody needs it.

    Thanks for putting this out.

    ReplyDelete
  38. The script works perfectly! Thank you very much for it.

    ReplyDelete

Please use family friendly language.