Just started with Applescript and combined some scripts to get the script and workflow i wanted.
Problem is it works fine with up to about 200 files but above that it gives an Time-Out error (~1712)
What can I do to speed up the script?
I will explain my workflow so that you can understand the steps I made.
My camera makes Raw and JPG files at the same time, I transfer the card to the computer, there I tag the jpg photo’s with red (delete), yellow (keep jpg) and orange (keep raw).
The AppleScript moves the yellow tags to a Temp Transport folder, red tags to the trash then compares the remaining JPG and Raw files and moves the corresponding Raw files to the Temp Transport folder then deletes all the leftover Raw images (the ones where we kept the JPG)
Complete Temp Transport folder is the moved to Downloads folder where Hazel takes over and sorts and renames the files in folder per day and timestamp in the name.
Maybe this is all too much info, but maybe it helps
My code:
tell application "Finder"
-- Move Yellow Tag to Transport folder
set sourceFolder to ("Macintosh HD :Users:User:Downloads:Workflow Raw JPG:Raw en JPG:") as alias
set TransportFolder to ("Macintosh HD :Users:User:Downloads:Workflow Raw JPG:Transport Downloads:") as alias
move (every file of sourceFolder whose label index is 3) to TransportFolder
-- Move Red Tag to Trash
move (every file of sourceFolder whose label index is 2) to the trash
-- Move videofiles to Transport Folder
move (every file of sourceFolder whose name extension is "mov") to TransportFolder
move (every file of sourceFolder whose name extension is "mp4") to TransportFolder
move (every file of sourceFolder whose name extension is "avi") to TransportFolder
-- Get the extension of the Raw files
set allJPG to every file of sourceFolder whose name extension is "jpg"
set allRAF to every file of sourceFolder whose name extension is "raf"
set allNEF to every file of sourceFolder whose name extension is "NEF"
set allCR2 to every file of sourceFolder whose name extension is "CR2"
set targetJPGFiles to my CompareNames(allJPG, allRAF, allNEF, allCR2)
end tell
targetJPGFiles -- This allows you to see the filenames that SHOULD have been tagged
to CompareNames(jp, pn, nf, cr)
--First, get rid of all the extensions in the RAW files
set cleanRAWNames to {}
set neededJPGNames to {}
-- RAF files
repeat with eachRAFName in pn
set end of cleanRAWNames to characters 1 thru -5 of (eachRAFName as text) as text
end repeat
-- NEF files
repeat with eachNEFName in nf
set end of cleanRAWNames to characters 1 thru -5 of (eachNEFName as text) as text
end repeat
-- CR2 files
repeat with eachCR2Name in cr
set end of cleanRAWNames to characters 1 thru -5 of (eachCR2Name as text) as text
end repeat
--Now, loop through JPG names to find a match
repeat with eachjpgName in jp
set searchName to characters 1 thru -5 of (eachjpgName as text) as text
if cleanRAWNames contains searchName then
set TempFolder to ("Macintosh HD :Users:User:Downloads:Workflow Raw JPG:Tijdelijk JPG:") as alias
set end of neededJPGNames to (eachjpgName as alias)
move eachjpgName to TempFolder
end if
end repeat
return neededJPGNames
end CompareNames
tell application "Finder"
--set fr to folder with RAW files
set fr to ("Macintosh HD :Users:User:Downloads:Workflow Raw JPG:Raw en JPG:") as alias
--set fj to folder with corresponding JPEG files
set fj to ("Macintosh HD :Users:User:Downloads:Workflow Raw JPG:Tijdelijk JPG:") as alias
set {rFiles, jFiles} to {fr's files as alias list, fj's files as alias list}
set {rNames, jNames} to {my stripExt(rFiles), my stripExt(jFiles)}
repeat with i from 1 to count rFiles
if rNames's item i is not in jNames then delete rFiles's item i
end repeat
end tell
to stripExt(fileList) -- removes extension so names can be compared
set nn to {}
tell application "Finder"
repeat with f in fileList
set nn's end to ¬
(f's name as text)'s text 1 thru -(((f's name extension as text)'s length) + 2)
end repeat
end tell
return nn
end stripExt
-- Empty folder with remaining JPG
tell application "Finder"
delete every item of entire contents of (TempFolder)
end tell
-- Move folder with sorted Photos to temp Downloads
tell application "Finder"
set sourceFolder to ("Macintosh HD :Users:User:Downloads:Workflow Raw JPG:Raw en JPG:") as alias
set TransportFolder to ("Macintosh HD :Users:User:Downloads:Workflow Raw JPG:Transport Downloads:") as alias
move every item of entire contents of (sourceFolder) to (TransportFolder)
-- Move folder with temp Downloads to Downloads for Hazel Rules
set DestinationtheFolder to ("Macintosh HD :Users:User:Downloads:") as alias
move every item of entire contents of (TransportFolder) to (DestinationtheFolder)
end tell
([code][/code] posting tags corrected to [applescript][/applescript] by NG.)
The main problem is that the Finder (like many applications) is very slow at making decisions based on ‘whose’ filters and in carrying those decisions. The more items it has to filter, the more bogged down it gets and the script eventually decides there’s not going to be a result — hence the timeout error you’re seeing. In your script, there are nine of these filters in succession, each of which requires the Finder to fetch and filter the information about all the files in the folder.
A better approach is to get the Finder simply to return all the information of interest in one go and to let the script itself filter this information and make the decisions. So for instance, the first Finder ‘tell’ statement in your script could be replaced with this:
set sourceFolder to ("Macintosh HD :Users:User:Downloads:Workflow Raw JPG:Raw en JPG:") as alias
set TransportFolder to ("Macintosh HD :Users:User:Downloads:Workflow Raw JPG:Transport Downloads:") as alias
-- Tell the Finder just to return the alias, label index, and name extension of every file in the folder.
-- The values in the three returned lists are in corresponding order. Item i in one list goes with item i in each of the other two.
tell application "Finder"
tell every file of folder (sourceFolder as text)
set {theFiles, labelIndices, nameExtensions} to {it, its label index, its name extension}
end tell
end tell
-- Let the script itself make the decisions based on the returned information.
set allJPG to {}
set allRAF to {}
set allNEF to {}
set allCR2 to {}
repeat with i from 1 to (count theFiles)
set thisFile to item i of theFiles
set thisLabelIndex to item i of labelIndices
if (thisLabelIndex is 2) then
-- Move Red Tag to Trash
tell application "Finder" to move thisFile to the trash
else if (thisLabelIndex is 3) then
-- Move Yellow Tag to Transport folder
tell application "Finder" to move thisFile to TransportFolder
else
set thisExtension to item i of nameExtensions
-- Move video files to Transport Folder. Add files with other extensions to the appropriate list.
if (thisExtension is in {"mov", "mp4", "avi"}) then
tell application "Finder" to move item thisFile to TransportFolder
else if (thisExtension is "jpg") then
set end of allJPG to thisFile
else if (thisExtension is "raf") then
set end of allRAF to thisFile
else if (thisExtension is "NEF") then
set end of allNEF to thisFile
else if (thisExtension is "CR2") then
set end of allCR2 to thisFile
end if
end if
end repeat
set targetJPGFiles to my CompareNames(allJPG, allRAF, allNEF, allCR2)
-- Rest of script.
There may also be other ways to speed things up, but this should get you started and will almost certainly cure the timeout problem.
By the way, it’s not considered a good idea to intersperse handlers with the main running code. Your CompareNames(jp, pn, nf, cr) and stripExt(fileList) handlers should both be written either above or below the main code, which is considered to be a ‘run handler’ in its own right.
Nigel has given you some excellent advice, but the prime suspect as cause of a timeout error is the use of entire contents on a folder with a lot of files. And you don’t need it here: a simple every item would do.
To better understand Nigel’s suggestion, I ran the first section with a path that contained several files:
set sourceFolder to ("Macintosh HD:Users:Robert:Working:") as alias
tell application "Finder"
tell every file of sourceFolder
set {theFiles, labelIndices, nameExtensions} to {it, its label index, its name extension}
end tell
end tell
I received the following error:
Just to see what was happening, I ran the following, which correctly returned all files in sourceFolder
set sourceFolder to ("Macintosh HD:Users:Robert:Working:") as alias
tell application "Finder" to set theFiles to every file of sourceFolder
I just randomly tried different alternatives, and the only script that would work was:
set sourceFolder to ("Macintosh HD:Users:Robert:Working:") as alias
tell application "Finder"
set theFiles to every file of sourceFolder
set {theFileLabels, theFileExtensions} to {label index, name extension} of every file of sourceFolder
end tell
I’m probably making some simple mistake, but I can’t figure it out.
I’m not accustomed to get an error when testing a Nigel’s script but this time I got the described error under 10.13.6 ans was forced to split the code in three instructions as you did.
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 8 aout 2020 16:47:59
Thanks peavine and Yvan and apologies to anyone who tried the code. I must admit I didn’t try it before posting this time, but was working from years of habit. It turns out (in Mojave at least) that the folder specifier in this case has to be a Finder one, not an alias. So:
set sourceFolder to ("Macintosh HD:Users:Robert:Working:") as alias
tell application "Finder"
tell every file of folder (sourceFolder as text)
set {theFiles, labelIndices, nameExtensions} to {it, its label index, its name extension}
end tell
end tell
Or even:
set sourceFolder to ("Macintosh HD:Users:Robert:Working:") as alias
tell application "Finder"
tell every file of folder sourceFolder
set {theFiles, labelIndices, nameExtensions} to {it, its label index, its name extension}
end tell
end tell
Thanks for the reply.
Updated the script and it works perfect. Did a test with about 500 files and it ran in about 15 seconds!
b.t.w. i put the intersperse handlers on the bottom of the script, tried it at the top fitst but that got an error of Target files not set, when set on the bottom the script worked magically.