Find and replace in file name in FInder

I wrote this script to find and replace a specified string of text with new text if it exists in the file name of any files in a selected folder. It basically works. The only thing it doesn’t do is replace multiple instances. If added this check so that a multiple instance wouldn’t mess up the script:

if the (count of text items of FileName) is 2 then
set NewName to (((first text item of FileName) as string) & ReplaceText & ((last text item of FileName) as string)) as text
set name of x to NewName
else
display dialog ("Text appears more than once. No changes made to " & FileName)
end if

Is there a way of getting it to do this easily. I can think of ways where it would go through every character and take a huge amount of text, but it seems like there should be an easy way to do it.

Here’s what I have:


set Folder2Process to (choose folder with prompt "Find and Replace all files in folder:") as alias
set FindText to text returned of (display dialog "What text to find:" default answer "")
set ReplaceText to text returned of (display dialog "Replace with:" default answer "")

tell application "Finder"
	set AllFiles to every file of entire contents of Folder2Process whose name does not start with "."
	repeat with x in AllFiles
		set FileName to name of x
		if FileName contains FindText then
			set AppleScript's text item delimiters to FindText
			if the (count of text items of FileName) is 2 then
				set NewName to (((first text item of FileName) as string) & ReplaceText & ((last text item of FileName) as string)) as text
				set name of x to NewName
			else
				display dialog ("Text appears more than once. No changes made to " & FileName)
			end if
		end if
	end repeat
end tell


Model: Mac G5
Operating System: Mac OS X (10.3.9)

Finder’s ‘entire contents’ command doesn’t list invisibles here, Matt-Boy. If it does for you, then you’ll need to reinstate your filter, by replacing the second line below with something like:

tell application "Finder" to repeat with f in (get files of Folder2Process's entire contents whose name does not start with ".")

Otherwise, you should find that something like this works reasonably well:

set tid to AppleScript's text item delimiters
tell application "Finder" to repeat with f in (get files of Folder2Process's entire contents)
    set fileName to f's name
    if findText is in fileName then
        set AppleScript's text item delimiters to findText
        set newName to fileName's text items
        set AppleScript's text item delimiters to replaceText
        set f's name to newName as string
    end if
end repeat
set AppleScript's text item delimiters to tid

Wow, that’s awesome. I didn’t know you could use applescript’s text item delimiters like that.

I took out the invisibles check. I had put it in there because I wasn’t sure if I needed it.

Thanks, kai.

I was looking around on the site and found that someone already posted a nice find and replace script at:

http://bbs.applescript.net/viewtopic.php?id=13509

Here’s the code as well if anyone wants to check it out:


set the source_folder to (choose folder with prompt "Folder containing items to edit:") as Unicode text

display dialog "Search and replace in:" buttons {"File Names", "Folder Names", "Both"} default button 3
set the search_parameter to the button returned of the result

repeat
	display dialog "Enter text to find in the item names:" default answer "" buttons {"Cancel", "OK"} default button 2
	set the search_string to the text returned of the result
	if the search_string is not "" then exit repeat
end repeat

repeat
	display dialog "Enter replacement text:" default answer "" buttons {"Cancel", "OK"} default button 2
	set the replacement_string to the text returned of the result
	if the replacement_string contains ":" then
		beep
		display dialog "A file or folder name cannot contain a colon (:)." buttons {"Cancel", "OK"} default button 2
	else if the replacement_string contains "/" then
		beep
		display dialog "A file or folder name cannot contain a forward slash (/)." buttons {"Cancel", "OK"} default button 2
	else
		exit repeat
	end if
end repeat

display dialog "Replace "" & the search_string & "" with "" & the replacement_string & "" in every item name?" buttons {"Cancel", "OK"} default button 2

tell application "Finder"
	-- Get a Finder reference to the relvant items.
	if (search_parameter is "Folder Names") then
		set item_reference to a reference to (folders of entire contents of folder source_folder whose name contains search_string)
	else if (search_parameter is "File Names") then
		set item_reference to a reference to (files of entire contents of folder source_folder whose name contains search_string)
	else
		set item_reference to a reference to (items of entire contents of folder source_folder whose name contains search_string)
	end if
	-- Get a list of aliases to the items.
	-- (Individual Finder references might fail when renaming items within renamed folders.)
	try
		set item_list to item_reference as alias list
	on error
		set item_list to item_reference as alias as list
	end try
	if item_list is not {} then
		-- If there are any relevant items, get their names.
		set current_names to name of item_reference
		-- Doctor each name...
		repeat with i from 1 to (count current_names)
			set astid to AppleScript's text item delimiters
			set AppleScript's text item delimiters to search_string
			set text_items to text items of (item i of current_names)
			set AppleScript's text item delimiters to replacement_string
			set new_item_name to text_items as Unicode text
			set AppleScript's text item delimiters to astid
			-- ... and rename the associated item.
			my set_item_name(item i of item_list, new_item_name)
		end repeat
	end if
end tell

beep 2

on set_item_name(this_item, new_item_name)
	tell application "Finder"
		--activate
		set the parent_container to (the container of this_item)
		if not (exists item new_item_name of the parent_container) then
			try
				set the name of this_item to new_item_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
				set new_item_name to my get_new_name(error_message, new_item_name)
				if (new_item_name is 0) then return 0
				my set_item_name(this_item, new_item_name)
			end try
		else --the name already exists
			--beep
			set new_item_name to my get_new_name("This name is already taken, please rename.", new_item_name)
			if (new_item_name is 0) then return 0
			my set_item_name(this_item, new_item_name)
		end if
	end tell
end set_item_name

on get_new_name(msg, default_answer)
	tell application (path to frontmost application as Unicode text)
		set {text returned:new_item_name, button returned:button_pressed} to (display dialog msg default answer default_answer buttons {"Cancel", "Skip", "OK"} default button 3)
		if (button_pressed is "OK") then
			return new_item_name
		else if (button_pressed is "Skip") then
			return 0
		else
			error number -128 -- only necessary on non-English systems.
		end if
	end tell
end get_new_name