Applescript not working with more than 300 files

Hi,

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 :wink:

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.)

Hope someone can help me.

Grt, Rob

Hi rdtaal. Welcome to MacScripter.

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.

@peavine

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 Yvan. I thought this issue might arise from the macOS version and it’s good to know that’s not the case.

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

I’ll correct my post above.

Hi Nigel,

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.