Bad Name for File

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?


[This script was automatically tagged for color coded syntax by Convert Script to Markup Code]

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. :frowning:

Dear Nigel,

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

This is what I have:


[This script was automatically tagged for color coded syntax by Convert Script to Markup Code]

Gosh, I’m sorry, mjmtaiwan! I was testing on one machine and typing my post in a hurry on another. You were right about the first typo:

set srcFldr to (item 1 of dropped items) as string

-- should be:

set srcFldr to (item 1 of droppedItems) as string

There’s also this:

set {folder_name, lst} to {name, name of items} of srcFldr

-- should be:

set {folder_name, lst} to {name, name of items} of folder srcFldr

I think that should fix it. Sorry for the inconvenience.

Great Nigel…

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.

Now… onward and upward :slight_smile:

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

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

Dear Nigel -

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

Thanks a million…

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

Does it make any difference on your machine?

Dear Nigel -

It looks like it should do what we’re looking for and I’m not getting any errors but for some reason the output pdf is only one page… the cover page.

Yours,

Mike

Hi, Mike.

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

Nigel-

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! :slight_smile:

Good luck! :slight_smile:

But recursive how? The entire folder hierarchy into one document? Individual documents at lower levels?

My thought was to make it recursive in handling many folders under an main folder with individual files generated per folder.

But there are many inconsistencies in the folders so it is best that I do it one by one. :?

Thanks again Nigel… your help is really appreciated by everyone here!

Mike