First… This great script was 99% written by dant with some modifications by yours truly (and thanks to jonn8 for the utility that converts it to bbcode)
When I drag a folder with over 31 characters in the folder name I get a “Bad Name for File” error. Under 31 characters, no problem - even with the “/” character (which I thought could not be in file/folder names). Also, folder names with spaces cause errors with joinPDF as I can’t seem to get a quoted form of the Posix path with the pdfs the way I have this set up.
I thought the 31 character limit went out with os9? What am I doing wrong?
You’re using a string as the parameter for ‘list folder’ instead of an alias or file specification. Try it this way:
set lst to (list folder (srcFldr as alias) without invisibles)
But you can also use the Finder:
on open droppedItems -- It's not a good idea to coerce this list parameter to string.
set srcFldr to (item 1 of dropped items) as string
tell application "Folder"
if class of item srcFldr is folder then
set {folder_name, lst} to {name, name of items} of srcFldr
else
error "This item is not a folder."
end if
end tell
-- etc.
I’m afraid I haven’t had time this morning to look at your POSIX paths.
Thanks for your remarks and guidance… I have always found your posts to be very informative and helpful.
I got an error running the second part of your hint so I used it as the basis of a stand alone test script, got errors, made some adjustments and am still getting errors.
I changed
set srcFldr to (item 1 of dropped items) as string
as I was getting a script error = “Expected “, ” but found plural class name.”
to
set srcFldr to (item 1 of droppedItems) as string
Now I get the "Can’t get name of “Platodog:Users:michaelmorrison:Desktop:TEST_Folder:” error
That fixed it for the long file name issue… I don’t know if I will ever get my head around references to files/folders as strings or as alias or as file or whatever.
Hi, mjmtaiwan. I’m comparatively ignorant about shell scripts so I’m not sure if I’ve correctly analysed the rest of your script. I think you’re going for a string of quoted POSIX paths, grouped (and lexically sorted) under the ‘rules’ that their names contain. If I’ve got that right, you might like the following - this time copy/pasted from a working script. On my machine, it produces a command string in the required form - but since my system doesn’t know anything about “JoinPDF”, I haven’t been able to test the shell script itself.
Sorry about the length, which is due to the use of a fast, vanilla, sort handler.
property rule_list : {"Fractal_Geometry", "Exhibits", "Salesmen", "Consent", "Other", "Supplemental_Information"}
on open droppedItems
-- A script object for speed of access to lists.
script o
property lst : missing value -- will be a list of Mac OS paths
property collector : missing value -- will be a list of parts for the shell-script string
end script
-- Only process the first item of this drop.
set srcFldr to (item 1 of droppedItems) as string
set saveDelim to AppleScript's text item delimiters
-- If the dropped item's a folder, get the paths to all the files in it.
tell application "Finder"
if class of item srcFldr is not folder then error "This item is not a folder."
set AppleScript's text item delimiters to return
set o's lst to text items of ((files of folder srcFldr) as Unicode text)
end tell
-- Initialise the shell-script string collector with the command name,
-- the destination file path, and the cover page path.
set AppleScript's text item delimiters to ":"
set folder_name to text item -2 of srcFldr
set destfile to (path to desktop as Unicode text) & "Compiled_PDFs:" & folder_name & ".pdf"
set cover_page to (path to desktop as Unicode text) & "Cover.pdf"
set o's collector to {"JoinPDF", quoted form of POSIX path of destfile, quoted form of POSIX path of cover_page}
-- For each string in 'rule_list', append to the collector
-- the POSIX forms of any (pdf) file paths that contain the 'rule'.
set lstLen to (count o's lst)
set r to (count o's collector)
repeat with i from 1 to (count rule_list)
set l to r + 1
set target to item i of my rule_list
repeat with j from 1 to lstLen
set pdf to item j of o's lst
if pdf contains target then
set r to r + 1
set end of o's collector to quoted form of POSIX path of pdf
end if
end repeat
-- If more than 1 path per rule, sort lexically.
if r > l then qsort(o's collector, l, r)
end repeat
-- Combine the collected fragments into one string.
set AppleScript's text item delimiters to space
set cmd to o's collector as Unicode text
set AppleScript's text item delimiters to saveDelim
do shell script cmd
beep
end open
-- Knapp/Garvey qsort
-- Sorts (a region of) a list.
-- Params: the list, the left and right indices of the region to be sorted.
on qsort(theList, l, r)
script o
property cutoff : 10
property p : theList
on qsrt(l, r)
set i to l
set j to r
set v to my p's item ((l + r) div 2)
repeat while (j > i)
set u to my p's item i
repeat while (u < v)
set i to i + 1
set u to my p's item i
end repeat
set w to my p's item j
repeat while (w > v)
set j to j - 1
set w to my p's item j
end repeat
if (i > j) then
else
set my p's item i to w
set my p's item j to u
set i to i + 1
set j to j - 1
end if
end repeat
if (j - l < cutoff) then
else
qsrt(l, j)
end if
if (r - i < cutoff) then
else
qsrt(i, r)
end if
end qsrt
on isrt(l, r)
set x to l
set z to l + cutoff - 1
if (z > r) then set z to r
set v to my p's item x
repeat with y from (x + 1) to z
if (my p's item y < v) then
set x to y
set v to my p's item y
end if
end repeat
tell my p's item l
set my p's item l to v
set my p's item x to it
end tell
set u to my p's item (l + 1)
repeat with i from (l + 2) to r
set v to my p's item i
if (v < u) then
set my p's item i to u
repeat with j from (i - 2) to l by -1
if (v < my p's item j) then
set my p's item (j + 1) to my p's item j
else
set my p's item (j + 1) to v
exit repeat
end if
end repeat
else
set u to v
end if
end repeat
end isrt
end script
set listLen to (count theList)
if (listLen > 1) then -- otherwise the handler will error
-- Translate negative indices
if (l < 0) then set l to listLen + l + 1
if (r < 0) then set r to listLen + r + 1
if (r = l) then
-- No point in sorting just one item
else
-- Transpose transposed indices
if (l > r) then
set temp to l
set l to r
set r to temp
end if
if (r - l < o's cutoff) then
-- Skip the Quicksort if cutoff or less items
else
o's qsrt(l, r)
end if
o's isrt(l, r)
end if
end if
return -- nothing
end qsort
That is one impressive script. Frankly… I’ll need to print it out and study it this evening before I have any idea what’s going on.
I used it right out of the bag and the first folder I drop on it worked. Then it started crashing. I commented out the do shell script line and the string is just what I need… but for some reason its crashing.
I’ll take another look this evening (and restart the mac - perhaps that will shake out whatever is going on.)
Right. I’m seeing that here too - with some folders but not with others. I can’t see why that should be, but it seems to be cured (here) by breaking up this line (in the Finder ‘tell’ block):
set o's lst to text items of ((files of folder srcFldr) as Unicode text)
… into:
set theFiles to files of folder srcFldr
set fileText to theFiles as Unicode text
set o's lst to text items of fileText
Yes, you’re right. That “correction” I posted is now losing the references the other files. It seems that AppleScript’s not quite as clever when handling Unicode text as it is, or at least was, with plain text
Here’s a replacement for the ‘open’ handler. (You’ll still need the ‘rule_list’ property and the ‘qsort()’ handler.) o’s lst is now set as a list of aliases and the POSIX paths are extracted from these instead of from the Unicode Mac OS paths as originally. It’s passed all tests here so far…
on open droppedItems
-- A script object for speed of access to lists.
script o
property lst : missing value -- will be a list of aliases
property collector : missing value -- will be a list of parts for the shell-script string
end script
-- Only process the first item of this drop.
set srcFldr to (item 1 of droppedItems) as Unicode text
-- If the dropped item's a folder, get the aliases of all the files in it.
tell application "Finder"
if class of item srcFldr is not folder then error "This item is not a folder."
try
set o's lst to files of folder srcFldr as alias list
on error
set o's lst to first file of folder srcFldr as alias as list
end try
end tell
-- Initialise the shell-script string collector with the command name,
-- the destination file path, and the cover page path.
set saveDelim to AppleScript's text item delimiters
set AppleScript's text item delimiters to ":"
set folder_name to text item -2 of srcFldr
set destfile to (path to desktop as Unicode text) & "Compiled_PDFs:" & folder_name & ".pdf"
set cover_page to (path to desktop as Unicode text) & "Cover.pdf"
set o's collector to {"JoinPDF", quoted form of POSIX path of destfile, quoted form of POSIX path of cover_page}
-- For each string in 'rule_list', append to the collector
-- the quoted forms of any of the files' POSIX paths that contain the 'rule'.
set lstLen to (count o's lst)
set r to (count o's collector)
repeat with i from 1 to (count rule_list)
set l to r + 1
set target to item i of my rule_list
repeat with j from 1 to lstLen
set pdf to POSIX path of item j of o's lst
if pdf contains target then
set r to r + 1
set end of o's collector to quoted form of pdf
end if
end repeat
-- If more than 1 POSIX path per rule, sort lexically.
if r > l then qsort(o's collector, l, r)
end repeat
-- Combine the collected fragments into one string.
set AppleScript's text item delimiters to space
set cmd to o's collector as Unicode text
set AppleScript's text item delimiters to saveDelim
do shell script cmd
beep
end open
Success! And no need to remove the spaces in the path names… very, very good!
Now is finding a way to make the script recursive.
Your efforts are way beyond the call and I hate to take up your time on this. Both you and dant have left my applescripting skills way behind to the point I no longer understand the script.
Thanks again Nigel…
now I’m off to make the script recursive… wish me luck!