file name rename script

Beeing an amateur photographer i have large collection of image files. On a regular basis I have to rename a lot of files. There are a commercial tools for this. But it also fun to do this from the command line. It is even more fun to combine bash commands with appelscripting. So I wrote an applescript which uses the bash commands “mv” and “sed” to rename files.

Writing the script was fun. however for the time beeing I have no more files to rename. So take this script for a test drive and see what you can do with it. My advice is to look at the code first and test it on some unimportant files. There will probably will be flaws in the programm, that I am not yet aware of. I also noticed that script slows down when more than a hundred files are selected. I therefore use the command line for renaming larger number of files. Any advice on ways of improving the script will be very appreciated. Especially the speed could be improved.

The script was edited with apple editor vs 2.2.1, OSX 10.7.2

Have fun,

HGP


--Rename script vs6
--Apple script to replace files in the finder based on the bash commands sed and mv. 
--
--Just select the files in the finder and run the script. SED is used to replace the text. Therefore regex can be used.
--Eg. [^.]*$ will find all find all file extensions
--Use a backward slash with the special characters in the regex. Eg \(foo\)
--Be careful the underlying bash command are powerful and there is no undo !!!!!
--Have fun and let me know if you find improvements or flaws in the code.
--H P
--
--used variabeles------------------------------------------------------------------------------------------------------------------------------
--
--
set fileNames to {}
set pathNames to {}
set my_path to {}
set myOutput to {}
set myCount to 0
set my_final_source to {}
set my_final_Destination to {}
set Preparations to {}
--
---------------------------------------------------------------------------------------------------------------------------------------------------

set myTimer to current date
--
--Test if there some item selected in finder
--
tell application "Finder"
	if selection is {} then
		beep
		display dialog "You have to select some files in the finder" & return & "The run the script again" giving up after 4
		error number -128
	end if
end tell
--
--choose text to replace
--
try
	--set myTarget to text returned of (display dialog "Fill in text to replace, escape special characters with \\ l --> " default answer "Think about regex  in sed!!" buttons ["Cancel", "Ok"] default button 2) --Line before addition of help
	--
	set myResult to display dialog "Fill in text to replace, escape special characters with \\ l --> " default answer "Think about regex  in sed!!" cancel button "Cancel" buttons {"Cancel", "Help", "OK"} default button 3
	--
	if button returned of myResult as string is equal to "Help" then
		showHelp()
	end if
	--
	set myTarget to text returned of myResult
	--
	set myGoal to text returned of (display dialog "Fill in new text" default answer "" buttons ["Cancel", "Ok"] default button 2)
	--
	--Preparations voor replacement
	--
	set Preparations to Prepare_Replacement(myTarget, myGoal)
	--
	--test whether there is something to replace
	--
	if (count items of (my_example of Preparations)) is equal to 0 then
		display dialog "nothing to replace the script will stop, " giving up after 3
		return -- stops the  programma
	end if
	--
	--This shows the list of files that will be replaced 
	--
	set gg to choose from list my_example of Preparations with prompt "Replace preview. No need to select them,just press replace (if you dare ;)) " default items 1 OK button name "Replace" cancel button name "Stop" with title "Decision Window" with multiple selections allowed and empty selection allowed
	
	if result is false then
		display dialog "You cancelled, that's OK" giving up after 1
		return
	end if
	--
	--Code for actual replacement-----------------------------------------------------------------
	--
	set myOutput to {}
	set myCount to 0
	repeat with my_final_source in my_Source of Preparations
		set myCount to myCount + 1
		set my_final_Destination to item myCount of my_Destination of Preparations
		set end of myOutput to do shell script "mv  -v " & quoted form of my_final_source & " " & quoted form of my_final_Destination
	end repeat
	display dialog "done" giving up after 1
on error
	return
end try
--
set myTimer to (current date) - myTimer
display dialog myTimer as string
--
--called procedures-----------------------------------------------------------------------------------------------------------------------------
--
on get_selection()
	try
		tell application "Finder"
			set fileNames to {}
			set pathNames to {}
			set theItems to selection
			repeat with itemRef in theItems
				set end of fileNames to name of itemRef
				set end of pathNames to (POSIX path of (folder of itemRef as alias))
			end repeat
		end tell
		return {pathNames:pathNames, fileNames:fileNames}
	on error
		display dialog "Something went wrong in get selection procedure"
		return
	end try
end get_selection
--
------------------------------------------------------------------------------------------------------------------------------
--
on Prepare_Replacement(myTarget, myGoal)
	--further preparations for replacement
	try
		set mySelection to get_selection() --call get selection procedure
		set myCount to 0
		set my_Source to {}
		set my_Replacement to {}
		set my_example to {}
		set my_Destination to {}
		repeat with i in fileNames of mySelection
			--
			set myCount to myCount + 1
			try
				set my_Replacement to (do shell script (("echo " & quoted form of i & " | sed 's/" & myTarget as text) & "/" & myGoal as text) & "/'")
			on error
				display dialog "Problem in replacement. It could be due to the limitions of SED "
				error number -128
			end try
			set end of my_Destination to (item myCount of pathNames of mySelection) & my_Replacement
			set end of my_Source to (item myCount of pathNames of mySelection) & i
			--
			try
				considering case
					if i as string is not equal to my_Replacement as string then
						set end of my_example to i & "  ------>  " & my_Replacement
					end if
				end considering
			on error
				display dialog "Something wrong in my_example variable"
			end try
			--
		end repeat
		return {my_Destination:my_Destination, my_Source:my_Source, my_example:my_example}
	on error
		display dialog "Something wrong in prepare replacement procedure"
		return
	end try
end Prepare_Replacement
--
------------------------------------------------------------------------------------------------
--
on showHelp()
	set helpText to "Rename script vs6       
Apple script to replace files in the finder based on the bash commands sed and mv.                   
Just select the files in the finder and run the script. SED is used to replace the text. Therefore regex can be used.         
Eg. [^.]*$ will find all find all file extensions         
Use a backward slash with the special characters in the regex. Eg \\(foo\\)         
Be careful the underlying bash command are powerful and there is no undo !!!!!          
Have fun and let me know if you find improvements or flaws in the code.         
H P"
	
	display dialog helpText
end showHelp
--
---------------------------------------------End of script----------------------------------------------------------


Model: Imac 3.06 Ghz core 2 Do
AppleScript: 2.2.1
Browser: Safari 534.52.7
Operating System: Mac OS X (10.7)

A quick once-over of the code indicates that the big bottleneck is in get_selection().

You could speed it up a lot by taking advantage of the speed that finder returns the current selection as text.

on get_selection()
	tell application "Finder"
		set oldDelims to AppleScript's text item delimiters
		set AppleScript's text item delimiters to return
		set sel to selection as string
		set AppleScript's text item delimiters to ":"
		set pathNames to text items of sel
		set AppleScript's text item delimiters to "/"
		set pathNames to pathNames as string
		set AppleScript's text item delimiters to return
		set pathNames to text items of pathNames
		set fileNames to {}
		set AppleScript's text item delimiters to "/"
		repeat with oneItem in pathNames
			set end of fileNames to text item -1 of oneItem
		end repeat
		set AppleScript's text item delimiters to oldDelims
		return {pathNames:pathNames, fileNames:fileNames}
	end tell
end get_selection

I gave this handler a try on 400 text files. This way took 0.4 seconds in Script Debugger, whilst the other way took 38 seconds.

You could make it quicker still by using sed to sort out the colons and suck out the fileNames with something like this:

set pathNames to do shell script "echo " & quoted form of sel & " | sed 's/:/\\//g'"

which would make it take about 25% of the time, but you’re not saving much by this point.