AppleScript

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:

Fix HTML Codes in Files

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

Next Project

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.

applescript.txt · Last modified: 2007/03/20 10:34 by scott
chimeric.de = chi`s home Creative Commons License Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0