I’m using OS X 10.3.9. I have a folder containing Word documents whose filenames have a number followed by one or more words. E.g., 1 Monterey, 2 Carmel Highlands, . . . 10 Seaside, 11 Marina, . . .
What I need to do is open a new empty Word document and insert all of the separate Word documents into it in numeric order as indicated above by their filenames. When I create a list of my folder contents using “list folder”, I get a purely alphabetic list, in which 1 Monterey is followed by 10 Seaside instead of 2 Carmel Highlands. I tried using a shell script to do the sort (do shell script “echo " & myList & " | sort -n”), without making any difference in the list.
Seems like a simple problem. Any suggestions?
Model: G4
Browser: Safari 312.6
Operating System: Mac OS X (10.3.9)
Unfortunately, these names are what shows up in print, and they don’t want leading zeros there. If necessary, I can strip leading zeroes from these filenames before embedding them in the concatenated documents, but I thought there’d be a more general solution that would essentially match the numeric sort which OS X gives to filenames.
set Fnames to {"11 Marina", "13 Homestead", "2 Carmel Highlands", "1 Monterey", "10 Seaside"}
set Fnums to {}
repeat with f in Fnames
set n to ""
repeat with c in characters of f
try
set c to c as integer
on error
exit repeat
end try
set n to n & c
end repeat
set end of Fnums to n as integer
end repeat
sort_items(Fnums, Fnames) -- now the list Fnames is numerically sorted.
to sort_items(sortList, SecondList) -- , thirdList) -- from a script by Kai
tell (count sortList) to repeat with i from (it - 1) to 1 by -1
set s to sortList's item i
set r to SecondList's item i
--set q to thirdList's item i
repeat with i from (i + 1) to it
tell sortList's item i to if s > it then
set sortList's item (i - 1) to it
set SecondList's item (i - 1) to SecondList's item i
-- set thirdList's item (i - 1) to thirdList's item i
else
set sortList's item (i - 1) to s
set SecondList's item (i - 1) to r
-- set thirdList's item (i - 1) to q
exit repeat
end if
end repeat
if it is i and s > sortList's end then
set sortList's item it to s
set SecondList's item it to r
-- set thirdList's item it to q
end if
end repeat
end sort_items
…or this, which will also sort any other files that can’t be evaluated as a number…
set inputList to {"6 String", "10 String", "2 String", "Chunky Monkey", "300 String", "Aardvark", "1 String"}
set outputList to {}
repeat with tmpItem in inputList
set tmpItem to (tmpItem as string)
set tmpItemNum to (numericPrefixForString(tmpItem))
set alreadyCopied to false
set tmpOutputList to {}
repeat with tmpOutItem in outputList
set tmpOutItem to (tmpOutItem as string)
set tmpOutItemNum to (numericPrefixForString(tmpOutItem))
if (valuesAreIntegers(tmpItemNum, tmpOutItemNum)) then
set {tmpItemNum, tmpOutItemNum} to {(tmpItemNum as integer), (tmpOutItemNum as integer)}
else
set {tmpItemNum, tmpOutItemNum} to {(tmpItemNum as string), (tmpOutItemNum as string)}
end if
if ((tmpItemNum < tmpOutItemNum) and (not alreadyCopied)) then
copy tmpItem to the end of tmpOutputList
set alreadyCopied to true
end if
copy tmpOutItem to the end of tmpOutputList
end repeat
if (not alreadyCopied) then copy tmpItem to the end of tmpOutputList
set outputList to tmpOutputList
end repeat
return outputList --> Here's your sorted list
(* * * * * * * * * * * * * Subroutines * * * * * *)
to numericPrefixForString(tmpString)
set AppleScript's text item delimiters to {" "}
try
set outNum to text item 1 of tmpString
on error
set outNum to null
end try
set AppleScript's text item delimiters to {""}
return outNum
end numericPrefixForString
to valuesAreIntegers(val1, val2)
try
(val1 as integer)
(val2 as integer)
return true
on error
return false
end try
end valuesAreIntegers
It would be better to use leading zeros in the Finder names, so when you get the listing you don’t need to sort. You’re inserting the names and the contents of each file, right? If this is the case, then you have to repeat through the listing anyway and you could just eliminate the leading zeros then.
If you go with leading zeros, here’s a quick way of stripping them from a list of strings:
set max_zeros to 2
set l to {"001a", "027b", "100c"}
set user_tid to AppleScript's text item delimiters
repeat max_zeros times
set AppleScript's text item delimiters to {tab}
set s to tab & (l as string)
set AppleScript's text item delimiters to {tab & "0"}
set l to rest of (text items of s)
end repeat
set s to l as string
set AppleScript's text item delimiters to {tab}
set l to text items of s
set AppleScript's text item delimiters to user_tid
l
Edited: I made an error somewhere in this script, but I have to go somewhere. I think I know where it is.
This seems to work, but something doesn’t look right:
-- creating sorted list
set lz to "00"
set lzl to length of lz
set sorted_list to {}
repeat with i from 1 to 999
set end of sorted_list to text -4 thru -1 of ("00" & i & "x")
end repeat
--set t1 to the ticks
set user_tids to AppleScript's text item delimiters
repeat lzl times
set AppleScript's text item delimiters to {tab}
set temp_s to tab & (sorted_list as string)
set AppleScript's text item delimiters to {tab & "0"}
set sorted_list to rest of (text items of temp_s)
end repeat
set AppleScript's text item delimiters to {tab}
set temp_s to sorted_list as string
-- remove double tabs
set AppleScript's text item delimiters to {tab & tab}
set temp_l to text items of temp_s
set AppleScript's text item delimiters to {tab}
set temp_s to temp_l as string
set sorted_list to (text items of temp_s)
set AppleScript's text item delimiters to user_tids
--set t2 to the ticks
--display dialog (t2 - t1)
sorted_list
Edited: had a good sleep and fixed it right up. It was the last item that was bugging me. For whatever reason, if you need to remove leading zeros from strings in a list, here’s the fixed script:
-- creating sorted list
set lz to "00"
set lzl to length of lz
set sorted_list to {}
repeat with i from 1 to 999
set end of sorted_list to text -4 thru -1 of ("00" & i & "x")
end repeat
--set t1 to the ticks
set user_tids to AppleScript's text item delimiters
repeat lzl times
-- tag the i th leading zeros
set AppleScript's text item delimiters to {tab}
set temp_s to tab & (sorted_list as string)
-- remove tags
set AppleScript's text item delimiters to {tab & "0"}
set sorted_list to rest of (text items of temp_s)
-- remove tabs from last item
if last item of sorted_list contains tab then
set temp_s to last item of sorted_list
set sorted_list to reverse of rest of reverse of sorted_list
set AppleScript's text item delimiters to {tab}
set temp_l to text items of temp_s
set sorted_list to sorted_list & temp_l
end if
--log sorted_list
end repeat
set AppleScript's text item delimiters to user_tids
--set t2 to the ticks
--display dialog (t2 - t1)
sorted_list
Jacques’s shell script seems simple and reliable for the current purpose. An extension of the idea would be to incorporate the folder listing into the shell script string:
tell (do shell script "ls -p " & quoted form of POSIX path of (choose folder) & " | sort -n")
if (it begins with "/") then
set sortedNames to paragraphs 2 thru -1
else
set sortedNames to paragraphs
end if
end tell
The “-p” parameter forces any subfolders or bundles to be listed with “/” at the ends of their names, making them easy to identify later on (if necessary). The if.else. block is because whereas “ls” only returns the folder contents on my 10.4.8 machine, the first line returned on my 10.2.8 machine is the POSIX path of the folder itself. I don’t know what the result would be in 10.3.9, so I’ve allowed for both possibilities. If it’s the same in Panther as Tiger, a one-liner will do the job:
set sortedNames to paragraphs of (do shell script "ls -p " & quoted form of POSIX path of (choose folder) & " | sort -n")
Nigel, you missed an “of” in your last post. If I leave it out, it compiles as “paragraph” instead of “paragraphs”, and throws an error on my machine.
set sortedNames to paragraphs of (do shell script "ls -F " & quoted form of POSIX path of (choose folder) & " | sort -n")
The only caveat I see to this extremely clean method, is that it doesn’t sort as osx does… as was requested by the original poster. I puts the lettered files first, rather than last in the final list. As we often find, there’s usually a better way using something other than applescript to do heavy lifting.
The first script works for me on a folder of any sort, but the one-liner fails (10.4.8) with "Can’t make paragraph “The list here” into type reference.
Thanks for pointing out the typo. I’ve now corrected it in my post and also changed the “-F” to “-p”, which doesn’t do all the other junk that “-F” does. I suppose it’s also truer to say that the shell script that Jacques posted was OP’s, which Jacques set up properly.
I was assuming that OP’s assertion that his folder contained files whose names began with numbers meant that all the files were like that.
Thanks for all the suggestions! Since my files all start with numbers, jobu’s one-liner seems to do the job just fine. Much more elegant than all that Applescript!