Need A Script to Check For Missing Files/Broken Serial # Ranges

Hello,

I am new to scripting and don’t even know where to start on this, so I am wondering if there is a way to do what I want.

I want to be able to run a script on a folder or group of folders to find out if there are any missing items in the folder, that is, if the series of items is missing any numbers. There might be more than one way to do this, and I’m open to any way that works.

The script should display a dialog when the folder doesn’t have the right number of files in it.

If it is possible to write a script that can spot whenever a series of files misses a number, that would be ideal. If not, maybe checking for the right number of items (described below) is possible.

In order to know what the number of files should be (and this is what I want to automate) I have to look at the serial numbers of the files within the folder. The number of files in the folder should equal [the highest serial # - the lowest serial #] plus 1.

Here is a real-life example. The folder to be looked at it contains a folder inside it and inside that is a set of serially numbered .dpx files numbered from 1000 to 1150.

tb0020_comp_v028 / ← folder to be acted upon by the script
2370x1800 /
tb0020_comp_v028.1000.dpx - tb0020_comp_v028.1150.dpx ← files to be looked at by the script

The script should look at the highest/last serial number (1150), subtract the lowest serial number (1000), add 1, and compare that to the number of .dpx files in the folder. There should be 151 files in the folder.

However we are able to arrive at the information, ideally, if the folder were missing one of the files in the series, the alert would say something like:

[center]“Broken Frames Detected! Missing tb0020_comp_v028.1032.dpx and tb0020_comp_v028.1047.dpx”
[/center]
Can anyone point me in the right direction as far as creating something like this?

Thank you very much,
Liat

You may try something like :

set theFolder to (path to desktop as text) & "store:"
tell application "System Events"
	set theNames to name of files of folder theFolder whose name extension is "dpx"
end tell
set missing to {}
set rootName to text 1 thru -9 of theNames's item 1
repeat with i from 1000 to 1150
	if rootName & i & ".dpx" is not in theNames then set end of missing to rootName & i & ".dpx"
	
end repeat
if missing is not {} then
	set theResult to "Broken Frames Detected! Missing " & my recolle(missing, " and ")
	display dialog theResult
end if


#=====

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

#=====

Yvan KOENIG running El Capitan 10.11.3 in French (VALLAURIS, France) mardi 1 mars 2016 19:07:01

Thank you so much for answering me! (I wanted to answer in French but I thought that would discourage general discussion).

In order to use the script correctly, where exactly should I paste in the file path to the folder?

For example, here is the file path of a folder I copied to my desktop to try the script:

Macintosh HD:Users:Fearless_Knitter:Desktop:ot0130_comp_v022

Thank you!
Liat

Model: MacBook Pro
AppleScript: 2.7
Browser: Safari 600.3.18
Operating System: Mac OS X (10.10)

To get the script working, I put in the file path (I had to remove the & “store”)…
But I got a dialog that listed every single file in the folder and said it was missing. Which makes sense because I messed with the script, but I just wanted you to know what I tried (below).

set theFolder to "Macintosh HD:Users:Fearless_Knitter:Desktop:ot0130_comp_v022:2370x1800" as text
tell application "System Events"
	set theNames to name of files of folder theFolder whose name extension is "dpx"
end tell
set missing to {}
set rootName to text 1 thru -9 of theNames's item 1
repeat with i from 1000 to 1150
	if rootName & i & ".dpx" is not in theNames then set end of missing to rootName & i & ".dpx"
	
end repeat
if missing is not {} then
	set theResult to "Broken Frames Detected! Missing " & my recolle(missing, " and ")
	display dialog theResult
end if


#=====

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

#=====

May you check that the names of the listed files really match what you described which means :

a root component “tb0020_comp_v028.”
a group of 4 digits in the range 1000.1150
the string “.dpx”

Here, when I ran it I got the events log :

tell current application
path to desktop as text
end tell
tell application “System Events”
get name of every file of folder “SSD 500:Users::desktop:store” whose name extension = “dpx”
end tell
tell application “Script Editor”
display dialog “Broken Frames Detected! Missing tb0020_comp_v028.1016.dpx and tb0020_comp_v028.1033.dpx”
end tell
Résultat :
{button returned:“OK”}

I guess that on your system, with the given path, the root component is “ot0130_comp_v022.” which means that the files are supposed to be named
from “ot0130_comp_v022.1000.dpx” to “ot0130_comp_v022.1150.dpx”

Yvan KOENIG running El Capitan 10.11.3 in French (VALLAURIS, France) mardi 1 mars 2016 20:58:48

The names do match what I described.

One thing to note is that the dpx files are in a folder that is within the main folder (it has to be like this), e.g.:

tb0020_comp_v028 / ← folder to be acted upon by the script
2370x1800 / ← intermediate folder
tb0020_comp_v028.1000.dpx - tb0020_comp_v028.1150.dpx ← files to be looked at by the script

What is the purpose of adding the word “store” to the file path?

Thank you so much for your help on this. I am so grateful.

Also, the number of .dpx files is not always 150. That was just an example. Sometimes there are 50, sometimes there are 200.

Hooray, I got the script to work! By manually entering the last serial number.

Is there any way the script can be modified to:

  1. Automatically detect the first and last serial numbers (for the “repeat with i from 1000 to 1150” part)?
  2. Run on the folder within the folder (because the file structure looks like this):

tb0020_comp_v028 / ← folder to be acted upon by the script
2370x1800 / ← intermediate folder
tb0020_comp_v028.1000.dpx - tb0020_comp_v028.1150.dpx ← files to be looked at by the script

Thank you!

I figured out how to do the second item myself (I added & “2370x1800” to the file path). Yay!

Now I just need to know how to tell the Script what the first and last serial numbers are.

Thank you!

Try :

--set theFolder to "Macintosh HD:Users:Fearless_Knitter:Desktop:ot0130_comp_v022:2370x1800" as alias # CAUTION, MUST be an alias !

set theFolder to choose folder

tell application "System Events"
	set theNames to name of files of theFolder whose name extension is "dpx"
end tell

# Sort the list of names
set theNames to clasSort(theNames, cmpasc)
# extracts the greater number
set higher to (text -8 thru -5 of last item of theNames) as integer

# I'm not sure that the two instructions below are useful
# I guess that normally the higher number is supposed to be a multiple of 10
set higherDiv10 to higher div 10
if higherDiv10 * 10 < higher then set higher to (higherDiv10 * 10) + 10

set missing to {}
set rootName to text 1 thru -9 of theNames's item 1
repeat with i from 1000 to higher
	if rootName & i & ".dpx" is not in theNames then set end of missing to rootName & i & ".dpx"
	
end repeat
if missing is not {} then
	set theResult to "Broken Frames Detected! Missing " & my recolle(missing, " and ")
	display dialog theResult
end if


#=====

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

#=====

(*
Tri par classement
-----------------
Implémentation: L. Sebilleau & D. Varlet
*)

on clasSort(lista, fcmp)
	if (count of lista) < 2 then return lista
	
	script listb
		property liste : lista
		property Compare : fcmp
	end script
	
	repeat with i from 2 to count of listb's liste
		set cle to item i of listb's liste
		repeat with j from i - 1 to 1 by -1
			if listb's Compare(cle, item j of listb's liste) then
				set item (j + 1) of listb's liste to item j of listb's liste
			else
				set j to j + 1
				exit repeat
			end if
		end repeat
		set item j of listb's liste to cle
	end repeat
	return listb's liste
end clasSort
----------- les fonctions de comparaison ------------

on cmpasc(n1, n2) -- pour le tri ascendant de nombres ou de chaînes
	return n1 < n2
end cmpasc

on cmpdesc(n1, n2) -- tri descendant de nombres ou de chaînes
	return n1 > n2
end cmpdesc

on cmpBothAsc(n1, n2) -- pour le tri ascendant de listes de nombres et de chaînes
	return n1 as text < n2 as text
end cmpBothAsc

on cmpBothDesc(n1, n2) -- tri descendant de de listes de nombres et de chaînes
	return n1 as text > n2 as text
end cmpBothDesc

on cmpNumAsc(n1, n2) -- pour le tri ascendant des nombres et des chaînes
	considering numeric strings
		n1 < n2
	end considering
	return result
end cmpNumAsc

on cmpNumDesc(n1, n2) -- tri descendant des nombres et des chaînes
	considering numeric strings
		n1 > n2
	end considering
	return result
end cmpNumDesc

on cmpLengthAsc(n1, n2) -- pour le tri ascendant des nombres et des chaînes
	return (count (n1 as text)) < (count (n2 as text))
end cmpLengthAsc

on cmpLengthDesc(n1, n2) -- tri descendant des nombres et des chaînes
	return (count (n1 as text)) > (count (n2 as text))
end cmpLengthDesc

# Sort lists of strings abc ⇥ def ⇥ ghi upon first substring before tab
on cmpLengthFirstDesc(t1, t2) -- USED HERE
	set {oTIDs, text item delimiters} to {text item delimiters, tab}
	set tt1 to text item 1 of t1
	set tt2 to text item 1 of t2
	set text item delimiters to oTIDs
	return (count tt1) > (count tt2)
end cmpLengthFirstDesc

# Sort list of lists of several items upon length of the first one
on cmpLengthFirstItemInList(L1, L2)
	return (count L1's item 1) > (count L2's item 1)
end cmpLengthFirstItemInList

#=====

I left several comparison codes unused here in the sort block of code.

Yvan KOENIG running El Capitan 10.11.3 in French (VALLAURIS, France) mardi 1 mars 2016 23:09:50

This can be done in many different ways, but I made a simple variant using Finder. There is no error trapping for insufficient”or no”dpx files, so you can make that improvement or just be aware of the limitation. You indicate that your range is variable, but I’m not sure if you realize that, by not using set numbers for the bounds, the first or last value in the range could be a missing item, and that will go unreported.

The basic concept in my method is:

set sampleFileName to "tb0020_comp_v028.1000.dpx"
set text item delimiters to "."
sampleFileName's text items -->{"tb0020_comp_v028", "1000", "dpx"} 

The filename’s item 2 is your target number in string form, and it can be coerced to an actual number. Extrapolate this to all files and compare each against the index bounded by the sorted values.


set text item delimiters to "."
set {folderPath, fileNames, missing} to {(choose folder) as text, {}, {}} 

tell application "Finder" to repeat with aFile in sort (folder folderPath's files whose name ends with ".dpx") by name 
	set fileNames's end to aFile's name
end repeat

--endpoints and the prefix/suffix
tell fileNames to set {min, max, fore, aft} to {item 1's text item 2 as number, item -1's text item 2 as number, item 1's text item 1, item 1's text item 3}

repeat with nombre from (min + 1) to (max - 1) --no need to retest known values
	try
		alias (folderPath & fore & "." & nombre & "." & aft) --if aliasable, then file exists and no error is produced
	on error
		set missing's end to nombre
	end try
end repeat

display dialog missing as text with title "Missing numbers:" with icon caution

Hi.

Here for the exercise is a method using ‘find’ to obtain and filter the file paths in order, ‘sed’ to extract the base name and serial numbers, and a vanilla loop to do the checking.

set theFolder to (choose folder)

-- This assumes the relevant files are always in a subfolder called "2370x1800" and have the name extension ".dpx".
set shellText to "find -f " & quoted form of (POSIX path of theFolder & "2370x1800") & " \\( -name '*.*.dpx' \\) |
sort -n -t '.' -k 2 |
sed -E '
# Extract the file name from each path.
s|^.+/([^/]+$)|\\1|
# Split the first name into the base name and ".", followed by a linefeed and the serial number.
1 s|([^.]+[.])([0-9]+)[.]dpx$|\\1\\'$'\\n''\\2|
# Reduce the other names to just the serial numbers.
2,$ s|^[^.]+[.]([0-9]+)[.]dpx$|\\1|'"

set foundNumbers to paragraphs of (do shell script shellText)
tell foundNumbers to set {baseName, firstNumber, lastNumber} to {beginning, item 2, item -1}
-- set foundNumbers to rest of foundNumbers -- Not really necessary.

set missingNames to "Files missing:"
repeat with thisNumber from firstNumber + 1 to lastNumber - 1
	if (thisNumber as text is not in foundNumbers) then
		set expectedName to baseName & thisNumber & ".dpx"
		set missingNames to missingNames & linefeed & expectedName
	end if
end repeat

if (missingNames ends with ".dpx") then
	display alert "Broken Frames Detected!" message missingNames
else
	display dialog "No breaks in the file name sequence." with icon note
end if

Edits: ‘sed’ code simplified; numeric sort added.

HI, Nigel. Your sed version mistakenly reports that there are no breaks in my foundNumbers sequence.

{“tb0020_comp_v028.”, “1000”, “1002”, “1004”, “999”}

Edit: Yvan’'s code in post 10 does not return any value.

@ Marc Antony

My guess is that you made something wrong.

I just ran the script extracted from the message #10 (I didn’t keep the original)
and got :

tell application “Script Editor”
choose folder
end tell
tell application “System Events”
get name of every file of alias “SSD 500:Users::desktop:store:” whose name extension = “dpx”
end tell
tell application “Script Editor”
display dialog “Broken Frames Detected! Missing tb0020_comp_v028.1016.dpx and tb0020_comp_v028.1033.dpx and tb0020_comp_v028.1152.dpx and tb0020_comp_v028.1153.dpx and tb0020_comp_v028.1154.dpx and tb0020_comp_v028.1155.dpx and tb0020_comp_v028.1156.dpx and tb0020_comp_v028.1157.dpx and tb0020_comp_v028.1158.dpx and tb0020_comp_v028.1159.dpx and tb0020_comp_v028.1160.dpx”
end tell
Résultat :
{button returned:“OK”}

I would not be too surprised to read that you made something wrong too when testing Nigel’s code.
I ran it after moving the files in the required subfolder (2370x1800) and I got :
tell application “Script Editor”
display alert “Broken Frames Detected!” message “Files missing:
tb0020_comp_v028.1016.dpx
tb0020_comp_v028.1033.dpx”
end tell
which matches what I got. The higher file available is numbered 1151 and as I wrote, I assumed that it was supposed to be a multiple of 10 which meant here 1160.

Yvan KOENIG running El Capitan 10.11.3 in French (VALLAURIS, France) mercredi 2 mars 2016 16:58:23

Ah right. That’s because I was assuming the serial numbers all contain the same number of digits, which was kinda implied by the exchange between Yvan and liatmgat in posts #5 and #6 above. Your “999”, being lexically greater than the other numbers, is sorted to the end of the list. But being numerically lower than the “first” number, it causes the repeat loop not to execute.

Post #7 indicates that there can be 10’s or 100’s of results, so I intuited a potential crossover. Maybe it will apply, and maybe it won’t. I thought Yvan’s code might similarly account for such a value change, with its explicit sort, but testing it after-the-fact shows that it doesn’t. When I removed my 999 value file, it actually adds missing items that are beyond my extant file range.

"display dialog "Broken Frames Detected! Missing tb0020_comp_v028.1001.dpx and tb0020_comp_v028.1003.dpx and [i][b]tb0020_comp_v028.1005.dpx and tb0020_comp_v028.1006.dpx and tb0020_comp_v028.1007.dpx and tb0020_comp_v028.1008.dpx and tb0020_comp_v028.1009.dpx and tb0020_comp_v028.1010.dpx[/b][/i]""

OK. I’ve now inserted a numeric sort into mine (post #12), just to be sure. It still assumes that the name format is basename.serialnumber.extension, with the serial number between the first and second dots.

My script does exactly what you described.
It seams that you just failed to read it carefully.
My late message was supposed to put you on the track but it didn’t.

I wrote :

I would not be too surprised to read that you made something wrong too when testing Nigel’s code.
I ran it after moving the files in the required subfolder (2370x1800) and I got :

It was important because in my original script I work upon files stored directly in theFolder.
Missing that - which was really clear in the code -:

set theFolder to choose folder

tell application "System Events"
   set theNames to name of files of theFolder whose name extension is "dpx"
end tell

What is ure is that liatmgat saw that. He was able to adapt my original proposal :
set theFolder to (path to desktop as text) & “store:”
as:
set theFolder to “Macintosh HD:Users:Fearless_Knitter:Desktop:ot0130_comp_v022:2370x1800” as text
which is the expanded form of :
set theFolder to (path to desktop as text) & “ot0130_comp_v022:2370x1800” as text
In fact, the ending as text is perfectly useless but as it didn’t hurt I didn’t commented it.

In the message #10 you referred to, the very first instruction is :

]set theFolder to[/u] “Macintosh HD:Users:Fearless_Knitter:Desktop:ot0130_comp_v022:2370x1800” as alias # CAUTION, MUST be an alias !
which was even more explicit/clear that my very first code.

Missing that, you applied it to a set of datas stored in a subfolder of theFolder and of course, as there was no dpx file in theFolder, you got the list theNames as an empty list.

For my point of view, if theFolder is built by a calculation, adding the string “2730x1800:” is a logical scheme at least if there are several subfolders to work upon.
If theFolder results of the use of a choose folder dialog as it does in my script my preferred scheme is to select the folder supposed to contain the files. This get rid of the need to assumes the relevant files are always in a subfolder called “2370x1800”

Yvan KOENIG running El Capitan 10.11.3 in French (VALLAURIS, France) mercredi 2 mars 2016 19:13:20

Hi, Yvan. You are not performing the same test that I am, which is where the misunderstanding lies.

WIth these files: {“tb0020_comp_v028.1000.dpx”, “tb0020_comp_v028.1002.dpx”, “tb0020_comp_v028.1004.dpx”, “tb0020_comp_v028.999.dpx”}, your script returns no result.
The problem appears to relate to your sort method. When the 999.dpx file is removed, higher is 1004. When it exists, higher is 1; since it’s actually lower, the repeat loop can’t begin. You may have intended the cmpasc handler to help flip the value, but that isn’t currently happening.

By removing file 999, your script returns more than the possible number of results.
The two lines you questioned in post 10 should be disabled.
–set higherDiv10 to higher div 10
–if higherDiv10 * 10 < higher then set higher to (higherDiv10 * 10) + 10

At the beginning my script searched numbers in the range 1000 . 1150 as it was described by the asker.
Later it was said that the upper limit may be different so I edited the script to determine the larger number used.
I assumed that the upper limit was supposed to be a multiple of 10.
It’s why I introduced the instructions :
set higherDiv10 to higher div 10
if higherDiv10 * 10 < higher then set higher to (higherDiv10 * 10) + 10

which may be replaced by the more efficient :
set higher to (round (higher / 10) rounding up) * 10

This said, back to your comments.

WIth these files: {“tb0020_comp_v028.1000.dpx”, “tb0020_comp_v028.1002.dpx”, “tb0020_comp_v028.1004.dpx”, “tb0020_comp_v028.999.dpx”}, your script returns no result.
The problem appears to relate to your sort method.

The problem is not the sort method, it’s that your list contains a name which doesn’t match the rule so that your incorrect name “tb0020_comp_v028.999.dpx” is returned at the very end of the sorted list.
With a correctly formed name - “tb0020_comp_v028.0999.dpx”
the sort return 1004 as the greater number available.
My complementary instructions replace this value by 1010.

When it exists, higher is 1; since it’s actually lower, the repeat loop can’t begin.
I don’t understand what allow you to state that if your wrong filename is removed my code returns 1 as higher number. It’s just a nightmare of you.

set theNames to {"tb0020_comp_v028.1000.dpx", "tb0020_comp_v028.1002.dpx", "tb0020_comp_v028.1004.dpx", "tb0020_comp_v028.999.dpx"}
# Sort the list of names
set theNames to clasSort(theNames, cmpasc)
# extracts the greater number
set higher to (text -8 thru -5 of last item of theNames) as integer
log result (*999*)
set higherDiv10 to higher div 10
if higherDiv10 * 10 < higher then set higher to (higherDiv10 * 10) + 10
log result (*1000*)
set theNames to {"tb0020_comp_v028.1000.dpx", "tb0020_comp_v028.1002.dpx", "tb0020_comp_v028.1004.dpx", "tb0020_comp_v028.0999.dpx"}
# Sort the list of names
set theNames to clasSort(theNames, cmpasc)
# extracts the greater number
set higher to (text -8 thru -5 of last item of theNames) as integer
log result (*1004*)
set higherDiv10 to higher div 10
if higherDiv10 * 10 < higher then set higher to (higherDiv10 * 10) + 10
log result (*1010*)

set theNames to {"tb0020_comp_v028.1000.dpx", "tb0020_comp_v028.1002.dpx", "tb0020_comp_v028.1004.dpx"}
# Sort the list of names
set theNames to clasSort(theNames, cmpasc)
# extracts the greater number
set higher to (text -8 thru -5 of last item of theNames) as integer
log result (*1004*)
set higher to (round (higher / 10) rounding up) * 10
log result (*1010*)

#=====

(*
Tri par classement
-----------------
Implémentation: L. Sebilleau & D. Varlet
*)

on clasSort(lista, fcmp)
	if (count of lista) < 2 then return lista
	
	script listb
		property liste : lista
		property Compare : fcmp
	end script
	
	repeat with i from 2 to count of listb's liste
		set cle to item i of listb's liste
		repeat with j from i - 1 to 1 by -1
			if listb's Compare(cle, item j of listb's liste) then
				set item (j + 1) of listb's liste to item j of listb's liste
			else
				set j to j + 1
				exit repeat
			end if
		end repeat
		set item j of listb's liste to cle
	end repeat
	return listb's liste
end clasSort
----------- les fonctions de comparaison ------------

on cmpasc(n1, n2) -- pour le tri ascendant de nombres ou de chaînes  -- USED HERE
	return n1 < n2
end cmpasc

on cmpdesc(n1, n2) -- tri descendant de nombres ou de chaînes
	return n1 > n2
end cmpdesc

on cmpBothAsc(n1, n2) -- pour le tri ascendant de listes de nombres et de chaînes
	return n1 as text < n2 as text
end cmpBothAsc

on cmpBothDesc(n1, n2) -- tri descendant de de listes de nombres et de chaînes
	return n1 as text > n2 as text
end cmpBothDesc

on cmpNumAsc(n1, n2) -- pour le tri ascendant des nombres et des chaînes
	considering numeric strings
		n1 < n2
	end considering
	return result
end cmpNumAsc

on cmpNumDesc(n1, n2) -- tri descendant des nombres et des chaînes
	considering numeric strings
		n1 > n2
	end considering
	return result
end cmpNumDesc

on cmpLengthAsc(n1, n2) -- pour le tri ascendant des nombres et des chaînes
	return (count (n1 as text)) < (count (n2 as text))
end cmpLengthAsc

on cmpLengthDesc(n1, n2) -- tri descendant des nombres et des chaînes
	return (count (n1 as text)) > (count (n2 as text))
end cmpLengthDesc

# Sort lists of strings abc ⇥ def ⇥ ghi upon first substring before tab
on cmpLengthFirstDesc(t1, t2)
	set {oTIDs, text item delimiters} to {text item delimiters, tab}
	set tt1 to text item 1 of t1
	set tt2 to text item 1 of t2
	set text item delimiters to oTIDs
	return (count tt1) > (count tt2)
end cmpLengthFirstDesc

# Sort list of lists of several items upon length of the first one
on cmpLengthFirstItemInList(L1, L2)
	return (count L1's item 1) > (count L2's item 1)
end cmpLengthFirstItemInList

#=====

Of course, if I was a sooth sayer, I would have guess that you used a number with less than 4 digits and would have use the comparator cmpNumAsc.

set theNames to {"tb0020_comp_v028.1000.dpx", "tb0020_comp_v028.1002.dpx", "tb0020_comp_v028.1004.dpx", "tb0020_comp_v028.999.dpx"}
# Sort the list of names
set theNames to clasSort(theNames, cmpNumAsc)
# extracts the greater number
set higher to (text -8 thru -5 of last item of theNames) as integer
log result (*1004*)
set higherDiv10 to higher div 10
if higherDiv10 * 10 < higher then set higher to (higherDiv10 * 10) + 10
log result (*1010*)
set theNames to {"tb0020_comp_v028.1000.dpx", "tb0020_comp_v028.1002.dpx", "tb0020_comp_v028.1004.dpx", "tb0020_comp_v028.0999.dpx"}
# Sort the list of names
set theNames to clasSort(theNames, cmpNumAsc)
# extracts the greater number
set higher to (text -8 thru -5 of last item of theNames) as integer
log result (*1004*)
set higherDiv10 to higher div 10
if higherDiv10 * 10 < higher then set higher to (higherDiv10 * 10) + 10
log result (*1010*)

set theNames to {"tb0020_comp_v028.1000.dpx", "tb0020_comp_v028.1002.dpx", "tb0020_comp_v028.1004.dpx"}
# Sort the list of names
set theNames to clasSort(theNames, cmpNumAsc)
# extracts the greater number
set higher to (text -8 thru -5 of last item of theNames) as integer
log result (*1004*)
set higher to (round (higher / 10) rounding up) * 10
log result (*1010*)

#=====

(*
Tri par classement
-----------------
Implémentation: L. Sebilleau & D. Varlet
*)

on clasSort(lista, fcmp)
	if (count of lista) < 2 then return lista
	
	script listb
		property liste : lista
		property Compare : fcmp
	end script
	
	repeat with i from 2 to count of listb's liste
		set cle to item i of listb's liste
		repeat with j from i - 1 to 1 by -1
			if listb's Compare(cle, item j of listb's liste) then
				set item (j + 1) of listb's liste to item j of listb's liste
			else
				set j to j + 1
				exit repeat
			end if
		end repeat
		set item j of listb's liste to cle
	end repeat
	return listb's liste
end clasSort
----------- les fonctions de comparaison ------------

on cmpasc(n1, n2) -- pour le tri ascendant de nombres ou de chaînes
	return n1 < n2
end cmpasc

on cmpdesc(n1, n2) -- tri descendant de nombres ou de chaînes
	return n1 > n2
end cmpdesc

on cmpBothAsc(n1, n2) -- pour le tri ascendant de listes de nombres et de chaînes
	return n1 as text < n2 as text
end cmpBothAsc

on cmpBothDesc(n1, n2) -- tri descendant de de listes de nombres et de chaînes
	return n1 as text > n2 as text
end cmpBothDesc

on cmpNumAsc(n1, n2) -- pour le tri ascendant des nombres et des chaînes -- USED HERE
	considering numeric strings
		n1 < n2
	end considering
	return result
end cmpNumAsc

on cmpNumDesc(n1, n2) -- tri descendant des nombres et des chaînes
	considering numeric strings
		n1 > n2
	end considering
	return result
end cmpNumDesc

on cmpLengthAsc(n1, n2) -- pour le tri ascendant des nombres et des chaînes
	return (count (n1 as text)) < (count (n2 as text))
end cmpLengthAsc

on cmpLengthDesc(n1, n2) -- tri descendant des nombres et des chaînes
	return (count (n1 as text)) > (count (n2 as text))
end cmpLengthDesc

# Sort lists of strings abc ⇥ def ⇥ ghi upon first substring before tab
on cmpLengthFirstDesc(t1, t2)
	set {oTIDs, text item delimiters} to {text item delimiters, tab}
	set tt1 to text item 1 of t1
	set tt2 to text item 1 of t2
	set text item delimiters to oTIDs
	return (count tt1) > (count tt2)
end cmpLengthFirstDesc

# Sort list of lists of several items upon length of the first one
on cmpLengthFirstItemInList(L1, L2)
	return (count L1's item 1) > (count L2's item 1)
end cmpLengthFirstItemInList

#=====

Yvan KOENIG running El Capitan 10.11.3 in French (VALLAURIS, France) jeudi 3 mars 2016 11:25:33