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