Bolish

Q: iPhoto - Automator Import Script Improvements

Hi All,

 

I'm mainly working on Lightroom but uses iPhoto to get a better integration into OS X.

My main issue was syncing both librairies and I came to this with an automator script that I'm proud about. I hope it could help some guys also.

I will detail my script below, but I basically have a Lightroom jpegs export into finder folders and an applescript that import them into iPhoto with correct album name.

I have 3 ideas to improve that workflow but didn't manage to script it.

 

1) First improvement - don't copy files during import to saves space.

For now, iPhoto is copying the files to the library during import.

I want to improve this script by not copying the files into iPhoto library during import but I didn't manage to do it.

I tried to uncheck the tick box "copy the files to iPhoto library" but it didn't works. Import works but files still copied into iPhoto library...

So, I'm struggling with HD space because I've the photos twice on my hard disk (once in folder, once in iPhoto library)

 

2) Make a daily check of my photo folder content to launch the script automatically during night if there were some changes.

Something like :

If photofolder content (qty of files) is different than the day before, launch the import process

Else

End if

 

3) Don't import hidden folder

The "dispense item incrementally" is also scanning hidden folder (e.g : 'album data.xml' folder) that I didn't want to appear into iPhoto library.

I didn't find any option to not scan hidden folders right now.

 

My workflow in Automator :

 

Delete current iPhoto library

Create new one

List photos folder with "dispense folder incrementally"

Set folder name as a variable

Import this folder content to new iPhoto album with the above variable as album name.

Loop until dispense folder incrementally is done

 

Hoping that my post could support some guys who need that kind of workflow and hoping you guys could support my needs!

 

Regards

Posted on Jun 28, 2014 11:40 AM

Close

Q: iPhoto - Automator Import Script Improvements

  • All replies
  • Helpful answers

Page 1 Next
  • by Jacques Rioux,Solvedanswer

    Jacques Rioux Jacques Rioux Jun 29, 2014 10:41 AM in response to Bolish
    Level 4 (3,418 points)
    Mac OS X
    Jun 29, 2014 10:41 AM in response to Bolish

    Hi,

     

     

    This worflow verify If the photofolder content (qty of files) is different than the day before.

    During import, this script does not copy the images into iPhoto library, if the check box "Copy the files to iPhoto library" is unchecked.

    This script does not list hidden folders.

    This script import JPEG's files only.

    This workflow has been tested on Mavericks only.

     

    Try this:

    Open Automator, select 'Application'

    Add the 'Run AppleScript' action.

    Clear all text in  the 'Run AppleScript' action.

    Copy/paste this script:

    set watchFolder to ("pathToWatchFolder" as POSIX file) as text -- remove 'pathToWatchFolder' in this line and drag/drop your folder between the two double quote.
    if watchFolder does not end with ":" then set watchFolder to watchFolder & ":"
    set txtFile to watchFolder & ":numberOfFiles.txt"
    set n1 to 0
    try
         set n1 to (read file txtFile) as integer -- the number of files (the day before)
    end try
    do shell script "/usr/bin/find " & (quoted form of POSIX path of watchFolder) & " -type f | wc -l >" & quoted form of POSIX path of txtFile -- update the number of files in file "numberOfFiles.txt"
    set n2 to (read file txtFile) as integer -- the number of files (now)
    
    
    if n1 is n2 or n2 = 0 then error -128 -- same number of files or no files (this leaves this process immediately).
    

    Important : change the path in the first line of this script.

     

     

    Add  your actions to (Delete current iPhoto library and to Create new one).

     

    Add the 'Run AppleScript' action.

    Clear all text in  the 'Run AppleScript' action.

    Copy/paste this script:

    set watchFolder to ("pathToWatchFolder" as POSIX file) as text -- remove 'pathToWatchFolder' in this line and drag/drop your folder between the two double quote.
    my getSubFolders({watchFolder})
    
    
    on getSubFolders(tFolders)
         repeat with f in tFolders
              tell application "System Events"
                   tell folder f
                        set jpegs to (POSIX path of files whose type identifier is "public.jpeg") -- get JPEG's file only
                        set ListSubF to (path of folders whose visible is true)
                        set tName to name
                   end tell
              end tell
              if jpegs is not {} then my import_To_iPhoto(tName, jpegs)
              if ListSubF is not {} then my getSubFolders(ListSubF)
         end repeat
    end getSubFolders
    
    
    on import_To_iPhoto(t_Name, theseFiles)
         tell application "iPhoto"
              repeat while importing is true -- wait if importing
                   delay 2
              end repeat
              set alb to new album name t_Name
              import from theseFiles to alb without force copy -- 'without force copy': use the advanced preference of iPhoto
         end tell
    end import_To_iPhoto
    

    Important : change the path in the first line of this script.

    Save the workflow..

     

     

     

    To make a daily check of your photo folder, You can use a Calendar events (this method is for Mavericks, it may be different on other versions of the OS X):

    Open the "Calendar" application.

    Create a  new event, set the repeat to 'Every  Day'.

    Set the alert to 'Custom', select "Open File" in the first popup, select "Others" in the second popup and choose your workflow (Application)

    Select "One day of event" in the third popup

    Change the hour in the field.

  • by Bolish,

    Bolish Bolish Jun 29, 2014 11:56 AM in response to Jacques Rioux
    Level 1 (0 points)
    Photos for Mac
    Jun 29, 2014 11:56 AM in response to Jacques Rioux

    I was so proud of my POS code...but I have to say that yours is terrific, working great!!!

    Thanks a lot!

     

    Seeing such a code gave me other improvements ideas and the willing to learn about applescript.

     

    Do you think that instead of checking the whole Photo folder, I could check sub-folders (albums) one by one and launch the import process only if the sub-folder changed?

    This would avoid me to delete / create the entire library but I would have to delete the concerned album in iPhoto before to re-import it.

     

    Last thing is about the first code that is checking the qty of files. I think it could be improved by checking if there is at least one file with a modification date > the last import date.

    What do you think?

    (it's necessary because of Lightroom. e.g : when I modify a picture in Lightroom that was already export to the jpeg folder, it replaces the old one, so qty will not change...)

     

    Anyway, once more thanks a lot.

     

    Cordialement :-)

  • by Bolish,

    Bolish Bolish Jun 29, 2014 1:34 PM in response to Jacques Rioux
    Level 1 (0 points)
    Photos for Mac
    Jun 29, 2014 1:34 PM in response to Jacques Rioux

    Hi Jacques,

     

    I went to fast... It seems something is wrong in the first part as the import is still launched even if I made no files qty modification between 2 runs.

    Do you have an idea?

  • by Bolish,

    Bolish Bolish Jun 29, 2014 2:18 PM in response to Bolish
    Level 1 (0 points)
    Photos for Mac
    Jun 29, 2014 2:18 PM in response to Bolish

    My mistake, code is working (counting and code exit works well)...Sorry for that.

     

    Any help on above questions (folder by folder & modification date) stills welcomed.

  • by Jacques Rioux,Helpful

    Jacques Rioux Jacques Rioux Jun 29, 2014 6:46 PM in response to Bolish
    Level 4 (3,418 points)
    Mac OS X
    Jun 29, 2014 6:46 PM in response to Bolish

    Hi,

     

    Bolish wrote:

     

    Any help on above questions (folder by folder & modification date) stills welcomed.

    I do not know how Lightroom exports the photos, I guess these sub-folders are at the root of the source folder and you have no other sub-folder in these sub-folders.

     

     

    Here is the script that will check the modification date of each sub-folder, it will update or create the albums if necessary.

     

    Important : This script will not work with Automator, because the property (list of dates and list of names) will be reseted when the process is completed.

    Open the "AppleScript Editor" application

    Copy/paste this script in the window:

    property oldModifDates : {} -- The value set by a property definition is not reset each time the script is run; instead, it persists until the script is recompiled.
    property oldFolderNames : {}
    
    
    set watchFolder to "pathToWatchFolder" -- remove 'pathToWatchFolder' in this line and drag/drop your folder between the two double quote. 
    set newFolderNames to {}
    set newModifDates to {}
    
    
    -- get the subfolders in source folder (at the root only)
    tell application "System Events"
         repeat with f in (get folders of folder watchFolder whose visible is true)
              tell f
                   set tName to name
                   set modifDate to modification date
                   set doIt to tName is not in oldFolderNames
                   if doIt then -- this name is not in the old list of folderNames
                        set end of newFolderNames to tName
                        set end of newModifDates to modifDate
                   else
                        set n to my getIndex(tName) -- this name is in the old list of folderNames, get the index of this name 
                        set oldMoDate to item n of oldModifDates
                        set doIt to oldMoDate is not modifDate -- compare the date
                   end if
                   if doIt then -- different modification dates or this name is not in old list
                        set jpegs to (POSIX path of files whose type identifier is "public.jpeg") -- get JPEG's file only 
                        my import_To_iPhoto(tName, jpegs) -- update album
                   end if
              end tell
         end repeat
    end tell
    if newFolderNames is not {} then
         set oldModifDates to newModifDates -- update list 
         set oldFolderNames to newFolderNames -- update list 
    end if
    
    
    on import_To_iPhoto(t_Name, theseFiles)
         tell application "iPhoto"
              repeat while importing is true -- wait if importing  
                   delay 2
              end repeat
              if exists album t_Name then
                   set alb to album t_Name
                   remove (photos of alb) from photo library album -- delete photos of this album in the master library (put the photos in the trash album)
              else
                   set alb to new album name t_Name
              end if
              import from theseFiles to alb without force copy -- 'without force copy': use the advanced preference of iPhoto  
         end tell
    end import_To_iPhoto
    
    
    on getIndex(t)
         set tc to count oldFolderNames
         repeat with i from 1 to tc
              if item i of oldFolderNames = t then return i
         end repeat
         return 0
    end getIndex
    

    Important : change the path in the fifth line of this script.

    Save as "Application".

    Change the application to launch in your "Calendar" event.

     

    Important, at the first time that you run the script (application), or if you reopen the script to change something or to recompile it, you will lose the contents of the property (the dates and the names), In this case, the script will update all albums since the oldModifDates property (a list) will be empty.

     

     

    If you want to sync iPhoto Albums (regular albums only) according to your subfolders.

    The script do the same as the one above, but it will remove any regular albums whose name is not in the list of subfolder's name (according to the names of the subfolders that you have in the photos folder).

    Just replace the lines 32 through 35 in the script with this:

    if newFolderNames is not {} then -- to synchronize regular album, this do nothing on smart album and folder album in iPhoto
         set oldModifDates to newModifDates -- update list 
         set oldFolderNames to newFolderNames -- update list
         tell application "iPhoto"
              set imAlb to name of last import album
              set albNames to name of albums whose its type is regular album and name is not imAlb
         end tell
         repeat with i in albNames -- check  the name of this album with the names of the subFolders
              set alb_Name to contents of i
              if alb_Name is not in newFolderNames then
                   --  delete this album because the subfolder no longer exists in the whole Photo folder.
                   tell application "iPhoto"
                        remove (photos of album alb_Name) from photo library album -- remove photos 
                        remove album alb_Name -- remove empty album
                   end tell
              end if
         end repeat
    end if
    
  • by Bolish,

    Bolish Bolish Jun 30, 2014 1:40 PM in response to Jacques Rioux
    Level 1 (0 points)
    Photos for Mac
    Jun 30, 2014 1:40 PM in response to Jacques Rioux

    Yes, you guess correctly, I've sub-folders (let's call it albums, without any sub-sub folders) at the root photo folder.

    I include script 2 in script one (line 32 to 35) as suggested for a better sync in case of some sub-folders will be deleted.

     

    I made roughly 5 different trials in different cases. Amazing. It's working wonderful.

     

    Would it be possible to replace modification date by modification date + hh:mm:ss?

    e.g : when you run the script 2 times in the same day, it re-import a folder that was imported during the first run even if not modified between run 1 and run 2.

     

    Also, to solve the issue where the script is starting with 0 legacy datas (reopen, recompile, or first time) and re-importing everything, it should be great if it could reset iPhoto library first in order to avoid duplicate import. Of course, before deleting old one, a dial box asking for confirmation.

     

    I'm also looking at a dial box at the beginning of the script that would ask for confirmation : "iPhoto Import / Your MAC wants to update iPhoto library, do you want to continue / OK,Cancel"

    I was able to do it in Automator, I will try do to it on Applescript.

     

    I don't want to overstrain you, nevertheless, it's so close to perfect that I can't stop here!!!

     

    Just to make you aware...I believe, this script is solving the issue of 90% of the guys working on Lightroom on a MAC. It's really powerful, needful, amazing.

    Since I'm searching for this kind of script (few months), I saw hundreds of threads related to piece of code trying to make what you managed to make in 2 days.

    You did a great job.

     

    Lot of thanks.

  • by Jacques Rioux,

    Jacques Rioux Jacques Rioux Jun 30, 2014 7:56 PM in response to Bolish
    Level 4 (3,418 points)
    Mac OS X
    Jun 30, 2014 7:56 PM in response to Bolish

    Hi,

     

    Bolish wrote:

     

     

    Would it be possible to replace modification date by modification date + hh:mm:ss?

    e.g : when you run the script 2 times in the same day, it re-import a folder that was imported during the first run even if not modified between run 1 and run 2.

     

    Hi,

     

    About the dates, the time is included in these dates.

    I made ​​a mistake, I put the two lines (which added names and dates in the lists) in a 'if' block , then it should be done before this block, This is why the script was importing the folder again.

     

    Here's the modified script :

    Also, I made ​​other changes in the script (I wrote the script in fewer lines)

     

    property oldModifDates : {} -- The value set by a property definition is not reset each time the script is run; instead, it persists until the script is recompiled.  
    property oldFolderNames : {}
    
    set watchFolder to "pathToWatchFolder" -- remove 'pathToWatchFolder' in this line and drag/drop your folder between the two double quote.   
    set newFolderNames to {}
    set newModifDates to {}
    
    -- get the subfolders in source folder (at the root only)  
    tell application "System Events"
         repeat with f in (get folders of folder watchFolder whose visible is true)
              tell f
                   set tName to name
                   set modifDate to modification date
                   set end of newFolderNames to tName -- add this name to new list
                   set end of newModifDates to modifDate -- add this date to new list
                   set doIt to tName is not in oldFolderNames
                   if not doIt then -- this name is in the old list of folderNames  then check modif date
                        set oldMoDate to my getOldModifDate(tName) -- get the index of this name in the list of names, this subRoutine return the old modif date at same index in the dates list
                        set doIt to oldMoDate is not modifDate -- compare the date , these dates contains the time
                   end if
                   if doIt then -- different modification dates or this name is not in old list  
                        set jpegs to (POSIX path of files whose type identifier is "public.jpeg") -- get JPEG's file only   
                        my import_To_iPhoto(tName, jpegs) -- update album  
                   end if
              end tell
         end repeat
    end tell
    if newFolderNames is not {} then -- to synchronize regular album, this do nothing on smart album and folder album in iPhoto  
         set oldModifDates to newModifDates -- update list   
         set oldFolderNames to newFolderNames -- update list  
         tell application "iPhoto"
              set imAlb to name of last import album
              set albNames to name of albums whose its type is regular album and name is not imAlb
         end tell
         repeat with i in albNames -- check  the name of this album with the names of the subFolders  
              set alb_Name to contents of i
              if alb_Name is not in newFolderNames then
                   --  delete this album because the subfolder no longer exists in the whole Photo folder.  
                   tell application "iPhoto"
                        remove (photos of album alb_Name) from photo library album -- remove photos   
                        remove album alb_Name -- remove empty album  
                   end tell
              end if
         end repeat
    end if
    
    on import_To_iPhoto(t_Name, theseFiles)
         tell application "iPhoto"
              repeat while importing is true -- wait if importing    
                   delay 2
              end repeat
              if exists album t_Name then
                   set alb to album t_Name
                   remove (photos of alb) from photo library album -- delete photos of this album in the master library (put the photos in the trash album)  
              else
                   set alb to new album name t_Name
              end if
              import from theseFiles to alb without force copy -- 'without force copy': use the advanced preference of iPhoto    
         end tell
    end import_To_iPhoto
    
    on getOldModifDate(t)
         set tc to count oldFolderNames
         repeat with i from 1 to tc
              if item i of oldFolderNames = t then return item i of oldModifDates
         end repeat
    end getOldModifDate
    
    

     

     

     

    Also, I forgot to say, do not forget to empty the trash in iPhoto occasionally, because the script will fill the trash, but there is no AppleScript command to empty.

     

    About 'reset iPhoto library and dialog box', I'll watch it later this week.

  • by Bolish,

    Bolish Bolish Jul 1, 2014 12:29 AM in response to Jacques Rioux
    Level 1 (0 points)
    Photos for Mac
    Jul 1, 2014 12:29 AM in response to Jacques Rioux

    Works like a charm. Thanks for update.

  • by Jacques Rioux,

    Jacques Rioux Jacques Rioux Jul 5, 2014 7:12 PM in response to Bolish
    Level 4 (3,418 points)
    Mac OS X
    Jul 5, 2014 7:12 PM in response to Bolish

    Hi,

     

     

    To show a dialog at the beginning of the script to ask for confirmation, and reset iPhoto library on first run or recompile :

    Put this script into line 3 of your script

     

    property firstRun : true
    display dialog "iPhoto Import / Your MAC wants to update iPhoto library, do you want to continue?"
    --- if you press Cancel in the dialog, this application or this script will stop immediately.
    if firstRun then -- ** reset iPhoto **
         set firstRun to false
         tell application "iPhoto"
              activate
              remove photos from photo library album
              remove albums
         end tell
         tell application "System Events" -- to empty the trash in iPhoto **** GUI Scripting, need Accesibility
              tell process "iPhoto" -- work on iPhoto 9.5.1 and OS X 10.9.4
                   set frontmost to true
                   key code 51 using {command down, shift down} -- simulate the shortcut (delete key + shift + command)
                   set i to 0
                   repeat until (exists sheet 1 of window 1) or i > 4 -- the dialog is displayed, or no sheet (because the trash is already empty).
                        delay 1
                        set i to i + 1
                   end repeat
                   if i < 5 then keystroke return -- button "OK"
              end tell
         end tell
    end if
    
    
    

     

    I tested on iPhoto 9.5.1 and OS X 10.9.4 only.

     

     

    Important, because this script use GUI Scripting:

    For security reasons, OS X Mavericks does not use a single setting to enable or disable Accessibility features system-wide (such as the “Enable access for assistive devices” checkbox used in previous versions of OS X). Applications, including AppleScript scripts and apps (“applets”), must be individually authorized to use Accessibility using the Security & Privacy preference pane in System Preferences.

     

    For Mavericks:

    Open the "Security & Privacy" pane of System Preferences, select the "Privacy" Tab, select "Accessibility" from left table.

    Click the lock icon in the lower left corner of the Security and Privacy pane and enter an admin name and password when prompted.

    Drag/drop your Script (application) into the table.

    Close the System Preferences window.

    You should now be able to use the GUI script in your Application on your Mac

     

    In previous versions of OS X:

    Enable Accessibility by clicking the checkbox labeled "Enable access for assistive devices" in the Universal Access System Preference pane.

  • by Bolish,

    Bolish Bolish Aug 7, 2014 11:45 PM in response to Jacques Rioux
    Level 1 (0 points)
    Photos for Mac
    Aug 7, 2014 11:45 PM in response to Jacques Rioux

    Hi Jacques,

     

    Sorry for late reply, I had to deal with some personal issues.

     

    Nevertheless, I had time to try above script, and there is an issue with the "remove photos from photo library album". Line 8.

    It crashes when the library is over roughly 1200 photos. Under that, it works.

    The error message is "Time out for an apple event".

     

    Should we maybe delete the albums one by one?

    Or

    Should we maybe delete the entire library file and create a new one? (not ideal because it would scrap everything...)

     

    In parallel, I reworked a little bit the dialog boxes, modified it and replaced it in the code. Once everything will work fine, I will post a final version.

  • by Jacques Rioux,

    Jacques Rioux Jacques Rioux Aug 8, 2014 6:13 AM in response to Bolish
    Level 4 (3,418 points)
    Mac OS X
    Aug 8, 2014 6:13 AM in response to Bolish

    Hi,

    Bolish wrote:

     

    Nevertheless, I had time to try above script, and there is an issue with the "remove photos from photo library album". Line 8.

    It crashes when the library is over roughly 1200 photos. Under that, it works.

    The error message is "Time out for an apple event".

     

    This error occurs when a command takes more than two minutes (AppleScript default).

     

    You must use a 'with timeout of x seconds' block , like this:

    with timeout of 0 seconds
        remove photos from photo library album
    end timeout
    
    

     

     

    If you specify 0 seconds, there will be no time limit.

    You can also specify a number of seconds:

    with timeout of 1800 seconds ----> an error occurs when the command takes more than 30 minutes
    
    
  • by Bolish,

    Bolish Bolish Mar 20, 2015 12:50 PM in response to Jacques Rioux
    Level 1 (0 points)
    Photos for Mac
    Mar 20, 2015 12:50 PM in response to Jacques Rioux

    Hi Jacques, All,

     

    I'm still struggling with this last part of the code 'reset iphoto'. Indeed, it's taking really too long to delete all the pictures. Most of the time, it's crashing, even when setting the time limit very high.

     

    Do you have an idea how we can improve that?

    I was thinking (and already made some trials but not fully working) by replacing the 'reset iphoto' part by : completely delete the *.photolibrary file and create a new library to start from scratch.

    Not sure if it's the better idea but it will at least solve the issue.

     

    Rest of the code is working like a charm.

     

    Thanks in advance for help.

     

    Regards, Fabrice

  • by Jacques Rioux,

    Jacques Rioux Jacques Rioux Mar 21, 2015 12:16 PM in response to Bolish
    Level 4 (3,418 points)
    Mac OS X
    Mar 21, 2015 12:16 PM in response to Bolish

    Hi,

    Bolish wrote:

     

    Hi Jacques, All,

     

    I'm still struggling with this last part of the code 'reset iphoto'. Indeed, it's taking really too long to delete all the pictures. Most of the time, it's crashing, even when setting the time limit very high.

     

    Do you have an idea how we can improve that?

    I was thinking (and already made some trials but not fully working) by replacing the 'reset iphoto' part by : completely delete the *.photolibrary file and create a new library to start from scratch.

     

    A solution is to use a existing empty library as a template to copy it :

     

    From the iPhoto application, create a new library, name it "Empty iPhoto Library", save it in "Pictures" folder of your Home.

    Switch to your normal iPhoto Library.

    Use this script to reset iPhoto, the script copy the "Empty iPhoto Library" package to replace the current iPhoto Library package.

     

    property firstRun : true

    display dialog "iPhoto Import / Your MAC wants to update iPhoto library, do you want to continue?"

    --- if you press Cancel in the dialog, this application or this script will stop immediately. 

    if firstRun then -- ** reset iPhoto ** 

      set firstRun to false

      quit application "iPhoto"

      do shell script "sleep 4"

      set p to path to preferences folder as text

      tell application "System Events"

      tell property list file (p & "com.apple.iPhoto.plist") to set lib_loc to value of property list item "LibraryPath"

      end tell

      do shell script "cp -fpR ~/Pictures/'Empty iPhoto Library.photolibrary' " & quoted form of lib_loc -- , the current library will be replaced by the empty library package

      activate application "iPhoto" -- open the empty library

    end if

  • by Jacques Rioux,

    Jacques Rioux Jacques Rioux Mar 21, 2015 12:39 PM in response to Jacques Rioux
    Level 4 (3,418 points)
    Mac OS X
    Mar 21, 2015 12:39 PM in response to Jacques Rioux

    To work correctly, use this script:

     

    property firstRun : true

    display dialog "iPhoto Import / Your MAC wants to update iPhoto library, do you want to continue?"

    --- if you press Cancel in the dialog, this application or this script will stop immediately.

    if firstRun then -- ** reset iPhoto **

      set firstRun to false

      quit application "iPhoto"

      do shell script "sleep 4"

      set p to path to preferences folder as text

      tell application "System Events"

      tell property list file (p & "com.apple.iPhoto.plist") to set lib_loc to value of property list item "LibraryPath"

      end tell

      set tPath to quoted form of lib_loc

      do shell script "rm -fr " & tPath & ";cp -fpR ~/Pictures/'Empty iPhoto Library.photolibrary' " & tPath -- , the current library will be replaced by the empty library package

      activate application "iPhoto" -- open the empty library

    end if

Page 1 Next