Get Files Whose Displayed Name Contains Even/Odd Numerals

In my two proposals the number of digits doesn’t matter.

@ Nigel
As I was not sure of what the asker really wanted, I choose to ask System Events to move “even” items in the “even” folder and “odd” items in the “odd” folder.
I thought that it was better than leaving a set in the original folder which would at last contain many files.

Here is an edited version using the same scheme than yours to identify even/odd names.

on extractNumber(txt)
	set listChars to text items of txt
	set maybe to ""
	repeat with i from 1 to count listChars
		if item i of listChars is in "0123456789" then exit repeat
	end repeat
	repeat with j from i to count listChars
		if item j of listChars is not in "0123456789" then
			set lastDigit to item (j - 1) of listChars
			if lastDigit is not in "0123456789" then
				set maybe to ""
				exit repeat
			else
				set maybe to (lastDigit is in "02468")
				exit repeat
			end if
		end if
	end repeat
	return maybe
end extractNumber


set sourceContainer to path to desktop as text
set sourceFolder to sourceContainer & "source:"
set destContainer to path to documents folder as text
set evenFolder to destContainer & "even:" # pair
set oddFolder to destContainer & "odd:" # impair

tell application "System Events"
	# Create the destination folders if they aren't available
	if not (exists folder evenFolder) then make new folder at end of folder destContainer with properties {name:"even"}
	if not (exists folder oddFolder) then make new folder at end of folder destContainer with properties {name:"odd"}
	# Grab the name of visibles files in the source folder
	set fileNames to name of disk items of folder sourceFolder whose visible is true
	
	repeat with aName in fileNames
		# Extract the first possible number embedded in the file name
		set maybe to my extractNumber(aName)
		# Don't move files whose name doesn't embed a number
		if maybe is not "" then
			if maybe then # move files embedding an even number
				move disk item (sourceFolder & aName) to folder evenFolder
			else # move files embedding an odd number
				move disk item (sourceFolder & aName) to folder oddFolder
			end if
		end if
	end repeat
end tell # System Events

Its slightly faster than my late one.

Yvan KOENIG running Yosemite 10.10.5 in French (VALLAURIS, France) samedi 26 septembre 2015 22:06:04

Hi Yvan.

Oops. Yes, you’re right. I missed the OP’s paragraph about wanting to do the same with odd numbers too. The odd numbers could be found with a similar shell script:

set odds to paragraphs of (do shell script "find -E " & quoted form of POSIX path of sourceFolder & " -maxdepth 1 -regex '.*[13579][^0-9/][^/]*'")

Hello Nigel

I’m not sure that calling twice do Shell Script would be faster than the plain Vanilla.
I compared my different versions with the move instructions disabled so I was able to put the treatment in a repeat 100 times loop allowing me to get meaningful results using Shane’s timer.
I an’t do the same with yours.


use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

set beg to current application's NSDate's |date|()
repeat 100 times
	# the code to measure
	delay 0.01
end repeat


set theDiff to (beg's timeIntervalSinceNow()) as real # CAUTION, it's a negative value
set theDiff to -theDiff
if theDiff > 1 then
	set maybe to " seconds"
else
	set maybe to " second"
end if
tell application "SystemUIServer" to display dialog "Done in : " & theDiff & maybe

It prove to be fine because when I run it as is, it ends with :
“Done in : 1,106330990791 seconds”
which means : 1 second for the 100 delays + 0,106 second for the execution of the 100 loops.

Yvan KOENIG running Yosemite 10.10.5 in French (VALLAURIS, France) samedi 26 septembre 2015 22:21:15

Hello Nigel

My understanding is that your code extract a possible number everywhere in the files paths.
So if the source folder is something like
my:beautiful:128th:folder:

every files will be moved in the even folder.

Am’I right ?

I tested and it appears that I am wrong but I don’t understand why.
If I reduce the shell command to
set evens to paragraphs of (do shell script “find -E " & quoted form of POSIX path of sourceFolder & " -maxdepth 1”)
I get a list of entire pathnames :
the source folder one
the embedded files ones.
What is restricting the search to the filenames ?

I got it.
It’s this subset of your comment : [and with no further "/"s in the path.] which explain why I was wrong.

Yvan KOENIG running Yosemite 10.10.5 in French (VALLAURIS, France) samedi 26 septembre 2015 22:28:14

I assumed both even/odd needed to be moved and that some files might either lack numbers or exceed the stated upper limit and should be left in the original folder.


set {isOdd, isEven} to {{}, {}}
set pPathList to do shell script "find ~/Desktop/source/ | egrep '\\d{1,3}'" --isolate files with 1-3 #'s
set integerList to (do shell script "echo " & pPathList & " | tr  -d '[:alpha:]; [:punct:]' ")'s paragraphs  --separate #'s

repeat with index from 1 to count integerList
	tell integerList's item index as number to if it ≥ 1 and it ≤ 200 then
		if (it mod 2) = 1 then
			set isOdd's end to pPathList's paragraph index as POSIX file as alias
		else
			set isEven's end to pPathList's paragraph index as POSIX file as alias
		end if
	end if
end repeat

tell application "Finder"
	if not (exists folder "odd") and not (exists folder "even") then
		make folder with properties {name:"odd"}
		make folder with properties {name:"even"}
	end if
	move isOdd to folder "odd"
	move isEven to folder "even"
end tell

Edited to remove the superfluous awk call.

how fast is this AppleScriptObjC code using Nigel’s regex ? it doesn’t consider the “move” part


use framework "Foundation"
use scripting additions

set sourceFolder to POSIX path of (choose folder)

set fileManager to current application's NSFileManager's defaultManager()
set directoryContents to fileManager's contentsOfDirectoryAtPath:sourceFolder |error|:(missing value)
set oddPredicate to current application's NSPredicate's predicateWithFormat:"SELF matches '.*[13579][^0-9/][^/]*'"
set oddResults to directoryContents's filteredArrayUsingPredicate:oddPredicate
set evenPredicate to current application's NSPredicate's predicateWithFormat:"SELF matches '.*[02468][^0-9/][^/]*'"
set evenResults to directoryContents's filteredArrayUsingPredicate:evenPredicate

log oddResults as list
log evenResults as list


Hello Stefan

On the same folder, with a loop repeating the job 100 times, my late one ended with:
“Done in : 0,317521989346 second”
with the same loop, yours ended with :
“Done in : 0,07390999794 second”

What’s long in my vanilla version is the instruction :
set fileNames to name of disk items of folder sourceFolder whose visible is true

The late message of the Original Asker make all our answers incorrect because none of us check that the limit to 200 is respected.
It’s late. I will try to edit my version tomorrow.
I’m unable to edit the shell commands.

In the edited version I will extract the list of filenames with your ASObjC instructions:

set fileManager to current application's NSFileManager's defaultManager()
set directoryContents to fileManager's contentsOfDirectoryAtPath:sourceFolder |error|:(missing value)
set fileNames to directoryContents as list

I will use Shane’s timer to compare the old fashioned scheme and the modern one.
I know that some users are reluctant to use such code but it’s time to remove the old dust.

Yvan KOENIG running Yosemite 10.10.5 in French (VALLAURIS, France) samedi 26 septembre 2015 23:37:06

For simple things, agreed. But when regular expressions are involved anyway, and the alternatives require some knowledge of several shell commands – including things like awk – it seems to me every bit as approachable, and a good place to start learning it.

Hi Yvan.

I’m not sure the OP does actually want to set a limit. (That would be up to him to clarify.) But assuming there are no leading zeros, these regexes (regices?) seem to do the job:

Even numbers from 2 to 200: ‘.^0-9[^0-9/][^/]
Odd numbers from 1 to 199: ‘.[^0-9]1?[0-9]?[13579][^0-9/][^/]

Hello Nigel

In its late message (2015/09/26 03:53:38 pm), Marc Anthony wrote :

I assumed both even/odd needed to be moved and that some files might either lack numbers or exceed the stated upper limit and should be left in the original folder.

Oops, Marc is a helper, not the original asker.

Yvan KOENIG running Yosemite 10.10.5 in French (VALLAURIS, France) dimanche 27 septembre 2015 12:26:19

Here are the announced tests.

(1) version using only vanilla code


use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

on extractNumber(txt)
	set listChars to text items of txt
	set maybe to ""
	repeat with i from 1 to count listChars
		if item i of listChars is in "0123456789" then exit repeat
	end repeat
	repeat with j from i to count listChars
		if item j of listChars is not in "0123456789" then exit repeat
		set maybe to maybe & item j of listChars
	end repeat
	return maybe
end extractNumber


set sourceContainer to path to desktop as text
set sourceFolder to sourceContainer & "source:"
set destContainer to path to documents folder as text
set evenFolder to destContainer & "even:" # pair
set oddFolder to destContainer & "odd:" # impair

tell application "System Events"
	# Create the destination folders if they aren't available
	if not (exists folder evenFolder) then make new folder at end of folder destContainer with properties {name:"even"}
	if not (exists folder oddFolder) then make new folder at end of folder destContainer with properties {name:"odd"}
	# Grab the name of visibles files in the source folder
	set beg to current application's NSDate's |date|()
	
	repeat 100 times
		set fileNames to name of disk items of folder sourceFolder whose visible is true
		--log fileNames
		repeat with aName in fileNames
			# Extract the first possible number embedded in the file name
			set maybe to my extractNumber(aName)
			# Don't move files whose name doesn't embed a number
			if (maybe is not "") and maybe as number ≤ 200 then
				--log maybe
				set maybe to (maybe as number) mod 2
				if maybe = 1 then # move files embedding an odd number
					--move disk item (sourceFolder & aName) to folder oddFolder
				else # move files embedding an even number
					--move disk item (sourceFolder & aName) to folder evenFolder
				end if
			end if
		end repeat
	end repeat
end tell # System Events

set theDiff to (beg's timeIntervalSinceNow()) as real # CAUTION, it's a negative value
set theDiff to -theDiff
if theDiff > 1 then
	set maybe to " seconds"
else
	set maybe to " second"
end if
tell application "SystemUIServer" to display dialog "Done in : " & theDiff & maybe

-->  "Done in : 0,339022994041 second"

(2) version using ASObjC code to read extract the list of files but vanilla code to extract the embedded numbers.


use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

on extractNumber(txt)
	set listChars to text items of txt
	set maybe to ""
	repeat with i from 1 to count listChars
		if item i of listChars is in "0123456789" then exit repeat
	end repeat
	repeat with j from i to count listChars
		if item j of listChars is not in "0123456789" then exit repeat
		set maybe to maybe & item j of listChars
	end repeat
	return maybe
end extractNumber


set sourceContainer to path to desktop as text
set sourceFolder to POSIX path of (sourceContainer & "source:")
set destContainer to path to documents folder as text
set evenFolder to destContainer & "even:" # pair
set oddFolder to destContainer & "odd:" # impair

tell application "System Events"
	# Create the destination folders if they aren't available
	if not (exists folder evenFolder) then make new folder at end of folder destContainer with properties {name:"even"}
	if not (exists folder oddFolder) then make new folder at end of folder destContainer with properties {name:"odd"}
	# Grab the name of visibles files in the source folder
	
	set beg to current application's NSDate's |date|()
	repeat 100 times
		set fileManager to current application's NSFileManager's defaultManager()
		set directoryContents to fileManager's contentsOfDirectoryAtPath:sourceFolder |error|:(missing value)
		set fileNames to directoryContents as list
		--log fileNames
		repeat with aName in fileNames
			# Extract the first possible number embedded in the file name
			set maybe to my extractNumber(aName)
			
			# Don't move files whose name doesn't embed a number
			if (maybe is not "") and maybe as number ≤ 200 then
				--log maybe
				set maybe to (maybe as number) mod 2
				if maybe = 1 then # move files embedding an odd number
					--move disk item (sourceFolder & aName) to folder oddFolder
				else # move files embedding an even number
					--move disk item (sourceFolder & aName) to folder evenFolder
				end if
			end if
		end repeat
	end repeat
end tell # System Events

set theDiff to (beg's timeIntervalSinceNow()) as real # CAUTION, it's a negative value
set theDiff to -theDiff
if theDiff > 1 then
	set maybe to " seconds"
else
	set maybe to " second"
end if
tell application "SystemUIServer" to display dialog "Done in : " & theDiff & maybe
-->  "Done in : 0,095301985741 second"

(3) version extracting the list of files with ASObjC code, filtering them with ASObjC code using Regex


use framework "Foundation"
use scripting additions

--set sourceFolder to POSIX path of (choose folder)
set sourceContainer to path to desktop as text
set sourceFolder to POSIX path of (sourceContainer & "source:")


set beg to current application's NSDate's |date|()
repeat 100 times
	set fileManager to current application's NSFileManager's defaultManager()
	set directoryContents to fileManager's contentsOfDirectoryAtPath:sourceFolder |error|:(missing value)
	set oddPredicate to current application's NSPredicate's predicateWithFormat:"SELF matches  '.*[^0-9]1?[0-9]?[13579][^0-9/][^/]*'"
	set oddResults to directoryContents's filteredArrayUsingPredicate:oddPredicate
	set evenPredicate to current application's NSPredicate's predicateWithFormat:"SELF matches '.*[^0-9](1?[0-9][02468]|[2468]|200)[^0-9/][^/]*'"
	set evenResults to directoryContents's filteredArrayUsingPredicate:evenPredicate
end repeat


set theDiff to (beg's timeIntervalSinceNow()) as real # CAUTION, it's a negative value
set theDiff to -theDiff
if theDiff > 1 then
	set maybe to " seconds"
else
	set maybe to " second"
end if
tell application "SystemUIServer" to display dialog "Done in : " & theDiff & maybe
-->  "Done in : 0,046254992485 second"
log oddResults as list
log evenResults as list


So, we may see that the greater reduction of duration is due to the replacement of vanilla code by ASObjC one to extract the list of files.
At least two complementary tests were possible :
(a) one using list file to extract the filenames but I dropped here because list files is deprecated for years
(b) one using the Finder as an alternative to System Events but as you certainly know, I dislike the Finder which most of the time is slower than System Events.

As you know, I’m really curious so I didn’t resisted to make other tests.
This time the scripts really moved the files which I moved back after each run.

(I) ASObjC code to get the names, vanilla to extract numbers.
I ran it twice.
First with dest folders defined as string, last with the dest folders defined as aliases.
I was surprised to see that using aliases is a slowdowner.


use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

on extractNumber(txt)
	set listChars to text items of txt
	set maybe to ""
	repeat with i from 1 to count listChars
		if item i of listChars is in "0123456789" then exit repeat
	end repeat
	repeat with j from i to count listChars
		if item j of listChars is not in "0123456789" then exit repeat
		set maybe to maybe & item j of listChars
	end repeat
	return maybe
end extractNumber


set sourceContainer to path to desktop as text
set sourceFolder to POSIX path of (sourceContainer & "source:")
set destContainer to path to documents folder as text
set evenFolder to destContainer & "even:" # pair
set oddFolder to destContainer & "odd:" # impair

tell application "System Events"
	# Create the destination folders if they aren't available
	if not (exists folder evenFolder) then make new folder at end of folder destContainer with properties {name:"even"}
	if not (exists folder oddFolder) then make new folder at end of folder destContainer with properties {name:"odd"}
	
	--set evenFolder to evenFolder as alias # pair
	--set oddFolder to oddFolder as alias # impair
	# Grab the name of visibles files in the source folder
	
	set beg to current application's NSDate's |date|()
	
	set fileManager to current application's NSFileManager's defaultManager()
	set directoryContents to fileManager's contentsOfDirectoryAtPath:sourceFolder |error|:(missing value)
	set fileNames to directoryContents as list
	--log fileNames
	repeat with aName in fileNames
		# Extract the first possible number embedded in the file name
		set maybe to my extractNumber(aName)
		
		# Don't move files whose name doesn't embed a number
		if (maybe is not "") and maybe as number ≤ 200 then
			--log maybe
			set maybe to (maybe as number) mod 2
			if maybe = 1 then # move files embedding an odd number
				move disk item (sourceFolder & aName) to folder oddFolder
			else # move files embedding an even number
				move disk item (sourceFolder & aName) to folder evenFolder
			end if
		end if
	end repeat
end tell # System Events

set theDiff to (beg's timeIntervalSinceNow()) as real # CAUTION, it's a negative value
set theDiff to -theDiff
if theDiff > 1 then
	set maybe to " seconds"
else
	set maybe to " second"
end if
tell application "SystemUIServer" to display dialog "Done in : " & theDiff & maybe
-->  "Done in : 0,021662950516 second"
-->  "Done in : 0,027228951454 second" if the folder are predefined as aliases

(II) ASObjC to grab the names, ASObjC to apply regex to filter


use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

--set sourceFolder to POSIX path of (choose folder)

set sourceContainer to path to desktop as text
set sourceFolder to POSIX path of (sourceContainer & "source:")
set destContainer to path to documents folder as text
set evenFolder to destContainer & "even:" # pair
set oddFolder to destContainer & "odd:" # impair

tell application "System Events"
	# Create the destination folders if they aren't available
	if not (exists folder evenFolder) then make new folder at end of folder destContainer with properties {name:"even"}
	if not (exists folder oddFolder) then make new folder at end of folder destContainer with properties {name:"odd"}
end tell
set beg to current application's NSDate's |date|()

set fileManager to current application's NSFileManager's defaultManager()
set directoryContents to fileManager's contentsOfDirectoryAtPath:sourceFolder |error|:(missing value)
set oddPredicate to current application's NSPredicate's predicateWithFormat:"SELF matches  '.*[^0-9]1?[0-9]?[13579][^0-9/][^/]*'"
set oddResults to directoryContents's filteredArrayUsingPredicate:oddPredicate
set evenPredicate to current application's NSPredicate's predicateWithFormat:"SELF matches '.*[^0-9](1?[0-9][02468]|[2468]|200)[^0-9/][^/]*'"
set evenResults to directoryContents's filteredArrayUsingPredicate:evenPredicate

tell application "System Events"
	repeat with aName in (oddResults as list)
		move file (sourceFolder & aName) to folder oddFolder
	end repeat
	repeat with aName in (evenResults as list)
		move file (sourceFolder & aName) to folder evenFolder
	end repeat
end tell
set theDiff to (beg's timeIntervalSinceNow()) as real # CAUTION, it's a negative value
set theDiff to -theDiff
if theDiff > 1 then
	set maybe to " seconds"
else
	set maybe to " second"
end if
tell application "SystemUIServer" to display dialog "Done in : " & theDiff & maybe
-->  "Done in : 0,020846009254 second"

(III) shell script to extract odd and even items, System Events to move them

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
(*
set sourceFolder to (choose folder with prompt "Select the source folder.")
set evensFolder to (choose folder with prompt "Select the folder for files with even numbers in their names.")
*)
set sourceContainer to path to desktop as text
set sourceFolder to POSIX path of (sourceContainer & "source:")
set destContainer to path to documents folder as text
set evenFolder to (destContainer & "even:") # pair
set oddFolder to (destContainer & "odd:") # impair

set beg to current application's NSDate's |date|()
-- Find files with names containing even numbers ” ie. whose POSIX paths contain an even digit followed by a non-digit which is not "/" and with no further "/"s in the path.
set evens to paragraphs of (do shell script "find -E " & quoted form of POSIX path of sourceFolder & " -maxdepth 1 -regex '.*[^0-9](1?[0-9][02468]|[2468]|200)[^0-9/][^/]*'")

set odds to paragraphs of (do shell script "find -E " & quoted form of POSIX path of sourceFolder & " -maxdepth 1 -regex '.*[^0-9]1?[0-9]?[13579][^0-9/][^/]*'")

tell application "System Events"
	repeat with thisFile in evens
		move file thisFile to folder evenFolder
	end repeat
	repeat with thisFile in odds
		move file thisFile to folder oddFolder
	end repeat
end tell

set theDiff to (beg's timeIntervalSinceNow()) as real # CAUTION, it's a negative value
set theDiff to -theDiff
if theDiff > 1 then
	set maybe to " seconds"
else
	set maybe to " second"
end if
tell application "SystemUIServer" to display dialog "Done in : " & theDiff & maybe

--> "Done in : 0,058142006397 second"

(IV) everything with do shell script

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
(*
set sourceFolder to (choose folder with prompt "Select the source folder.")
set evensFolder to (choose folder with prompt "Select the folder for files with even numbers in their names.")
*)
set sourceContainer to path to desktop as text
set sourceFolder to quoted form of POSIX path of (sourceContainer & "source:")
set destContainer to path to documents folder as text
set evenFolder to quoted form of POSIX path of (destContainer & "even:") # pair
set oddFolder to quoted form of POSIX path of (destContainer & "odd:") # impair

set beg to current application's NSDate's |date|()
-- Find files with names containing even numbers ” ie. whose POSIX paths contain an even digit followed by a non-digit which is not "/" and with no further "/"s in the path.
set evens to paragraphs of (do shell script "find -E " & sourceFolder & " -maxdepth 1 -regex '.*[^0-9](1?[0-9][02468]|[2468]|200)[^0-9/][^/]*'")

set odds to paragraphs of (do shell script "find -E " & sourceFolder & " -maxdepth 1 -regex '.*[^0-9]1?[0-9]?[13579][^0-9/][^/]*'")


repeat with thisFile in evens
	do shell script "mv " & quoted form of thisFile & " " & evenFolder
end repeat
repeat with thisFile in odds
	do shell script "mv " & quoted form of thisFile & " " & oddFolder
end repeat


set theDiff to (beg's timeIntervalSinceNow()) as real # CAUTION, it's a negative value
set theDiff to -theDiff
if theDiff > 1 then
	set maybe to " seconds"
else
	set maybe to " second"
end if
tell application "SystemUIServer" to display dialog "Done in : " & theDiff & maybe

--> "Done in : 0,117416977882 second"

The result was so bad that I decided to replace the final loops by a more Unix aware scheme.

(V) This time, the groups of quoted forms of pathnames are moved in a single call.

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
(*
set sourceFolder to (choose folder with prompt "Select the source folder.")
set evensFolder to (choose folder with prompt "Select the folder for files with even numbers in their names.")
*)
set sourceContainer to path to desktop as text
set sourceFolder to quoted form of POSIX path of (sourceContainer & "source:")
set destContainer to path to documents folder as text
set evenFolder to quoted form of POSIX path of (destContainer & "even:") # pair
set oddFolder to quoted form of POSIX path of (destContainer & "odd:") # impair

set beg to current application's NSDate's |date|()
-- Find files with names containing even numbers ” ie. whose POSIX paths contain an even digit followed by a non-digit which is not "/" and with no further "/"s in the path.
set evens to paragraphs of (do shell script "find -E " & sourceFolder & " -maxdepth 1 -regex '.*[^0-9](1?[0-9][02468]|[2468]|200)[^0-9/][^/]*'")

set odds to paragraphs of (do shell script "find -E " & sourceFolder & " -maxdepth 1 -regex '.*[^0-9]1?[0-9]?[13579][^0-9/][^/]*'")

set evensList to {}
repeat with thisFile in evens
	set end of evensList to quoted form of thisFile
end repeat
set oddsList to {}
repeat with thisFile in odds
	set end of oddsList to quoted form of thisFile
end repeat

do shell script "mv " & my recolle(evensList, " ") & " " & evenFolder
do shell script "mv " & my recolle(oddsList, " ") & " " & oddFolder

set theDiff to (beg's timeIntervalSinceNow()) as real # CAUTION, it's a negative value
set theDiff to -theDiff
if theDiff > 1 then
	set maybe to " seconds"
else
	set maybe to " second"
end if
tell application "SystemUIServer" to display dialog "Done in : " & theDiff & maybe

--> "Done in : 0,065730988979 second"

#=====

on recolle(l, d)
	local oTIDs, t
	set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
	set t to l as text
	set AppleScript's text item delimiters to oTIDs
	return t
end recolle

#=====

Ouf, that’s all folks.

So, the faster is the scheme using ASObjC to extract the filenames and filter them with regex.
But, as the difference is short, for my own use, if I have to apply a different filter I will try to build a vanilla one because for me, Regex is resembling to ancient Chinese.

Yvan KOENIG running Yosemite 10.10.5 in French (VALLAURIS, France) dimanche 27 septembre 2015 16:49:20

Yvan,

A couple of things. It seems to me that, at least in theory, a name could contain two numbers and therefore match both rules, which would cause problems with the regex. Also, the regex is not filtering out invisible files. If you still have the folders set up, perhaps you can time this version too:

use AppleScript version "2.4"
use framework "Foundation"
use scripting additions

set sourceContainer to path to desktop as text
set sourceFolder to POSIX path of (sourceContainer & "source:")
set destContainer to path to documents folder as text
set evenFolder to POSIX path of (destContainer & "even:") # pair
set oddFolder to POSIX path of (destContainer & "odd:") # impair
-- make NSStrings of paths
set sourcePath to current application's NSString's stringWithString:sourceFolder
set oddDestPath to current application's NSString's stringWithString:oddFolder
set evenDestPath to current application's NSString's stringWithString:evenFolder

set fileManager to current application's NSFileManager's defaultManager()
-- create folders if they don't exist
fileManager's createDirectoryAtPath:oddDestPath withIntermediateDirectories:true attributes:(missing value) |error|:(missing value)
fileManager's createDirectoryAtPath:evenDestPath withIntermediateDirectories:true attributes:(missing value) |error|:(missing value)
-- get lists of file names and filter them
set directoryContents to fileManager's contentsOfDirectoryAtPath:sourcePath |error|:(missing value)
set oddPredicate to current application's NSPredicate's predicateWithFormat:"(NOT SELF BEGINSWITH '.') AND (SELF MATCHES '.*[^0-9](1?[0-9][02468]|[2468]|200)[^0-9/][^/]*')"
set oddResults to (directoryContents's filteredArrayUsingPredicate:oddPredicate) -- as list
set evenPredicate to current application's NSPredicate's predicateWithFormat:"(NOT SELF BEGINSWITH '.') AND (SELF MATCHES '.*[^0-9]1?[0-9]?[13579][^0-9/][^/]*')"
set evenResults to (directoryContents's filteredArrayUsingPredicate:evenPredicate)

-- build lists of odd source and destination paths
set oddPaths to sourcePath's stringsByAppendingPaths:oddResults
set oddDests to oddDestPath's stringsByAppendingPaths:oddResults
-- move odd files
repeat with i from 1 to oddPaths's |count|()
	(fileManager's copyItemAtPath:(oddPaths's objectAtIndex:(i - 1)) toPath:(oddDests's objectAtIndex:(i - 1)) |error|:(missing value))
end repeat
-- build lists of even source and destination paths
set evenPaths to sourcePath's stringsByAppendingPaths:evenResults
set evenDests to evenDestPath's stringsByAppendingPaths:evenResults
-- move even files
repeat with i from 1 to evenPaths's |count|()
	(fileManager's copyItemAtPath:(evenPaths's objectAtIndex:(i - 1)) toPath:(evenDests's objectAtIndex:(i - 1)) |error|:(missing value))
end repeat

Hi, Shane. My statement in post #4 could be viewed as hypocritical, given the code I posted. I didn’t intend that to be a starting point for the OP; it was more for experimentation and comparison amongst the regulars, since a workable and more easily understood vanilla method had already been given. Simple is good.

@Nigel:
I spent (an inordinate amount of) time coming up with an alternate even numbers pattern that permits zeros {0, 0x, and 00x}, while limiting the string to 200. It works fine in TextWrangler, but I forgot that neg/pos lookaheads and behinds don’t work in egrep. :frowning: I read somewhere that this might be suitable for a Perl pattern, but I don’t know how to implement that yet. Here it is, for posterity, in all its current uselessness:

((?<!\d)|[01]?(?<![2-9])\d{1})[2468]{1}(?!\d)|((?<!\d)|(?<!\d)\d{1,2})[0]{1,2}(?!\d)

Thanks Shane

(1) my vanilla filter extracts the first number available in a fileName. If they are two, the second one is ignored. I don’t know what to do.

(2) If I understand well, the different codes using regex may be slightly enhanced.
At this time they scan twice the source folder then try to move the files.
My guess is that it would be more efficient to
scan for one family of numbers, move the identified files to the wanted folder
then
scan for the other family of numbers, move the identified files to the wanted folder
Doing that the second scan apply to a smaller number of files so it would be faster.

(3) Of course, all tests were done with the same files from the same source folder and to the same destination folder.
I used a script to move the files back to the source after every attempt.

(4) I tested your proposal.
To be fair, I disabled the two instructions supposed to create the destination folders because they are out of the timed code in other versions.
The timer returned : “Done in : 0,006505012512 second”

BUT there is a drawback, the script doesn’t move the files, it copy them to the destinations but the originals remain in the source folder.

So, I opened Xcode, entered its help and search for copyItemAtPath.
Some lines below the displayed line, I found the function moveItemAtPath.
I replaced copyItemAtPath by moveItemAtPath in the script.
After emptying the destination folders I ran the edited script and got : “Done in : 0,002121984959 second”

More than 10 times faster than faster one of the scripts tested yesterdays.
We got here a new example of the efficiency of ASObjC.

For sure, the used syntax may appear as a bit esoteric but, with the samples which you posted several times here or in the list applescript-users@lists.apple.com, we have a lot of starting points which may be edited to fit specific needs.

On my side I stored numerous ones in a rtf file from which I extract them when needed.
I know that we may store them in Libraries but as you know, most of the scripts I write aren’t for my own use but are answers to askers and in such cases, except when the asker is using Mavericks, leaving the code in the script is easier.

Yvan KOENIG running Yosemite 10.10.5 in French (VALLAURIS, France) lundi 28 septembre 2015 10:16:00

I’d be inclined to wait for an “Oh by the way I forgot to mention .” response from the OP before worrying about that. One would need to know which number was relevant in such a case.

I have the opposite problem. SInce I usually use regex with egrep and sed, I keep forgetting how to use lookaheads and behinds and have to look them up every time. :wink:

Thanks for doing the test; sorry about leaving copy instead of move in there.

Which is sort of how many of us learned to script in the first place.

Yes, although I was thinking more in terms of how some of the example scripts would behave when a file is found by both regexes (none of your regicide here, thank you ;)), and it’s already been moved by the time the second lot of moving is attempted.

Not a problem. It was a good way to push me to search in Xcode’s help.
Often, the names given to features - probably clear for those whose English is the main language - are a bit complicated for me but in this case my old scholar English was sufficient.

Yvan KOENIG running Yosemite 10.10.5 in French (VALLAURIS, France) lundi 28 septembre 2015 14:21:39

Wow guys. Thanks for the responses. I’ll just be over here picking up my brain which just oozed out me ear.

Here’s the background for the script. I have bunch of PDF’s created from scans of a book that I want to recombine to re-create the book. However, they were all scanned in using a copy machine that didn’t have any sorting or collating functions. As a result, the original was scanned twice; once in a regular position and the second time upside down. The first scan yielded the correct orientation of the binding on the even pages. The second scan yielded the correct orientation of the binding on the odd pages. If you combine the even pages of the first scan and the odd pages of the second scan into one PDF file, you can then print 2 sided and have a book you just need to run through a 3 hole punch and put in a binder.

I thought there might be an easy way to use a list of numbers up to 200 (since I knew there wasn’t more than 200 pages in the original) to separate the files.

To resume the problem, according to my understanding,

(1) There was no risk to have two numbers embedded in a file name which is fine because we have no way to decide which one would be significant if they were two or more.
(2) There was no real need to drop numbers greater than 200.
This time you have less than 200 files but on day the original document may have more than 200 pages.
(3) It seems that the availability of zeros in front of numerical value was not a problem.

Yvan KOENIG running Yosemite 10.10.5 in French (VALLAURIS, France) mardi 29 septembre 2015 10:27:06