Wow, AppleScript is freaking horrible. In the attempt to make it “english like” they really, really make it hard to understand. Instead of it just being concise, it's confusing. And it doesn't clear up the fact that to do some things you want to do - you have to resort to “tricky” programming.
Case in point. I wrote a script to rename some files - to get rid of the HTML codes. I'm sure someone has already done this, but when I download my files from my web outlook on the mac, sometimes I get HTML codes for the spaces and other characters (like the ampersand).
Well, the apple stuff is confusing on two levels. Working with files and folders is not straight forward. Sometimes when you get a file it's an object even though it looks like a string, and you have to get another object from the alias to do anything to it you would think would be obvious. Why doesn't the base file have these attributes/methods if it really is an object? Why do I have to get an info object to get the info about the file? Arg.
Then comes the string replacement. Instead of having robust string operations, I have to resort to trickery - like changing the AppleScript language string delimiters and then converting the file into a list of parts, change the delimiters to the replacement, and put it all back.
At least Perl has s/find-str/replace-str/ - so you know what is being looked for and what is being replaced. Not AppleScript though. We can't be that obvious. We have to hide it and burry it with verbose but useless text. Arg.
So here's the code that works:
A note about formatting. AppleScript allows contractions. That's right. You can say AppleScript's to denote possession. This messes up most text formatters like the one below because it thinks a string is opened.
(* Fix HTML codes in a file name Variation on Apple's example rename script I still don't fully understand the finder's file and object methods. When you use aliases, when it's an object and not a string, what attributes the objects have and when. It's very confusing. *) tell application "Finder" to set the source_folder to (folder of the front window) as alias set path_name to source_folder as string set folder_info to info for source_folder set folder_name to name of folder_info display dialog "Fix All Files in Folder: " & folder_name buttons {"Cancel", "Choose", "Okay"} default button 3 -- Just in case the user doesn't want the front finder window to get renamed if button returned of result is "Choose" then choose folder with prompt "Select Folder To Rename" default location source_folder without invisibles and multiple selections allowed set source_folder to result end if set the file_list to list folder source_folder without invisibiles repeat with i from 1 to (count of file_list) set this_file to item i of the file_list set this_file to (path_name & this_file) as alias set this_file_info to info for this_file set current_name to the name of this_file_info -- for some reason I'm still getting hidden files so... -- skip them if they start with a "." if first character of current_name is not "." then -- We don't do folders! if folder of this_file_info is false then -- Fix the files -- Note: I need to know two things after a change, the new file name -- AND if the file name needs changing at all. I could probably create -- and object to handle this but I don't know how to do that yet. -- so I pass back a list that has what I need. set {new_name, change_space} to replaceHTML("%20", " ", current_name) -- Spaces first set {new_name, change_amp} to replaceHTML("%26", "&", new_name) -- Then ampersands (* FOR TESTING set {new_name, change_space} to replaceHTML(" ", "%20", current_name) -- Spaces first set {new_name, change_amp} to replaceHTML("&", "%26", new_name) -- Then ampersands display dialog "Change [" & current_name & "] to [" & new_name & "]" buttons {"Ok"} default button 1 *) -- add more codes as they become known if change_space or change_amp then rename_file(this_file, new_name) end if end if end if end repeat on replaceHTML(html_string, replacement_string, name_string) (* this routine contains the mojo. The trick here is to change applescripts default delimiters for strings, then use the "word" property to let applescript parse the words. The delimiters are removed. Then stitch it back together for your new word *) set AppleScript's text item delimiters to the html_string set the file_name_pieces to every text item of the name_string -- break name into pieces if (count of file_name_pieces) > 1 then -- one piece means it had not match set AppleScript's text item delimiters to replacement_string set new_file_name to the file_name_pieces as string -- Stitches it all back together. set change_it to true else set new_file_name to name_string set change_it to false end if set AppleScript's text item delimiters to "" return {new_file_name, change_it} end replaceHTML (* Rename the file checking for conflicts Note: this_file is a file ALIAS (not a string) - not sure what difference that makes but apparently it's important new_file_name is the name to set the file to. *) on rename_file(this_file, new_file_name) tell application "Finder" --activate set the parent_container_path to (the container of this_file) as text if not (exists item (the parent_container_path & new_file_name)) then try set the name of this_file to new_file_name on error the error_message number the error_number if the error_number is -59 then set the error_message to "This name contains improper characters, such as a colon (:)." else --the suggested name is too long set the error_message to error_message -- "The name is more than 31 characters long." end if --beep tell me to display dialog the error_message default answer new_file_name buttons {"Cancel", "Skip", "OK"} default button 3 copy the result as list to {new_file_name, button_pressed} if the button_pressed is "Skip" then return 0 my rename_file(this_file, new_file_name) end try else --the name already exists --beep tell me to display dialog "This name is already taken, please rename." default answer new_file_name buttons {"Cancel", "Skip", "OK"} default button 3 copy the result as list to {new_file_name, button_pressed} if the button_pressed is "Skip" then return 0 my rename_file(this_file, new_file_name) end if end tell end rename_file
After this I would like to write a script to automatically move my video files into my project directory cache. Possibily renaming them to something less obscure than the default name they get from the Sony Camera)
Also, it would be nice to get a real debugger and development environment for AppleScript.