Replace text in subfolders

I’m trying to modify the ‘Replace Text In Item Names’ sample script to work in subfolders. I have read a couple of other posts on using the recursive function, however I’ve no idea what I’m doing. So I hope somebody has a fast, easy answer on how to modify this.


set the item_list to list folder source_folder without invisibles
set source_folder to source_folder as string
repeat with i from 1 to number of items in the item_list
	set this_item to item i of the item_list
	set this_item to (source_folder & this_item) as alias
	set this_info to info for this_item
	set the current_name to the name of this_info
	set change_flag to false
	if the current_name contains the search_string then
		if the search_parameter is "Folder Names" and ¬
			folder of this_info is true then
			set the change_flag to true
		else if the search_parameter is "File Names" and ¬
			folder of this_info is false then
			set the change_flag to true
		else if the search_parameter is "Both" then
			set the change_flag to true
		end if
		if the change_flag is true then
			-- replace target string using delimiters
			set AppleScript's text item delimiters to the search_string
			set the text_item_list to every text item of the current_name
			set AppleScript's text item delimiters to the replacement_string
			set the new_item_name to the text_item_list as string
			set AppleScript's text item delimiters to ""
			my set_item_name(this_item, new_item_name)
		end if
	end if
end repeat

I found a OS 9 script that does what I want, but it doesn’ t work in OS X. I tried changing the OS X script by editing the line:

set the item_list to list folder source_folder without invisibles

to:


set the item_list to every item of the source_folder

and:

set the item_list to entire contents of the source_folder

and numerous variations of those lines, but they return errors that they “can’t get every item.” I take it these methods no longer work in OS X?

In reading the previous posts, I’m just not sure how to apply them to my script, as what I tried didn’t work.

FYI, the script I’m attempting to modify is available in the sample Finder scripts installed w/ OS X.

Any and all help is appreciated. :slight_smile:

I don’t know why your line variations weren’t working, but this version - rewritten from scratch - works on both my X and 8.6 machines. The ‘try’ block and ‘as list’ coercions are probably not necessary in X.

on change_item_names(source_folder, search_parameter, search_string, replacement_string)
  tell application "Finder"
    try
      -- Get the names to be changed
      if search_parameter contains "Folder" then
        set target_names to (name of folders of source_folder whose name contains search_string) as list
      else if search_parameter contains "File" then
        set target_names to (name of files of source_folder whose name contains search_string) as list
      else
        set target_names to (name of items of source_folder whose name contains search_string) as list
      end if
      
      -- Change the names of the items with those names
      set astid to AppleScript's text item delimiters
      repeat with i from 1 to (count target_names)
        set this_name to item i of target_names
        set AppleScript's text item delimiters to search_string
        set text_items to this_name's text items
        set AppleScript's text item delimiters to replacement_string
        set name of item this_name of source_folder to text_items as string
      end repeat
      set AppleScript's text item delimiters to astid
    on error
    end try
    
    -- Recurse through the subfolders
    set the_folders to source_folder's folders
    repeat with this_folder in the_folders
      my change_item_names(this_folder, search_parameter, search_string, replacement_string)
    end repeat
  end tell
end change_item_names

change_item_names(choose folder, "File Names", "aardvark", "fred")

How does this script work? When I run it, it asks for a folder to process, then… nothing :?:

Hmmm. I can only think of two reasons why it’s not working for you. Either this is another example of OS X Finder scripts working differently on different people’s machines, or you’re running the script exactly as I posted it. If it’s the latter, here’s the explanation. (Apologies if you already know this.)

The script is written in the form of a “handler”, which is a piece of code than can be invoked from anywhere in the script - including inside the handler itself. In this case, the handler effectually calls itself, which is what recursion means in scripting terms. The handler keeps calling itself at a particular point within itself, until some condition is met which stops it doing this. More on recursion later.

I’ve called this particular handler change_item_names:

on change_item_names(source_folder, search_parameter, search_string, replacement_string)
  -- The code that the handler executes goes here
end change_item_names

The four variables in the parentheses in the first line are the handler’s parameters. They’ll be set to the values in the corresponding positions of the line that “calls” the handler. The last line in the script I posted was an example of such a calling line.

change_item_names(choose folder, "File Names", "aardvark", "fred")

As I have no idea what text you want to replace with what, I just put some silly stuff into the line, assuming that you’d see from the parameter names in the handler what they were supposed to be. Sorry if this wasn’t clear. The four parameters should be:

  1. An alias to the folder itself. Here, I’ve used the command ‘choose folder’, which will run when the call line runs and provide the chosen folder’s alias.

  2. The string “File Names”, “Folder Names”, or “Both”. These are the possible values of the variable search_parameter in your original script.

3/4. The other two parameters are respectively the text you want to replace and the text with which you want to replace it. The effect of my example call line is that if the names of any files in the chosen folder (or its subfolders) contain “aardvark”, those names will be changed to contain “fred” instead. If none of the files’ names contain “aardvark” - as is highly probable - absolutely nothing will happen. You should use your own text here.

The handler’s recursive calls take place in the repeat loop at the end, and each call acts on a subfolder within the folder currently being treated. If there are no subfolders in the folder, the repeat loop isn’t executed and so neither are any recursive calls. The handler ends at that point, so the action then returns to the line that called it - which will be either the one in the repeat loop again (in the previous iteration of the handler, which is going throug the folders in this folder’s parent folder) or - eventually - the line which made the original call - the one at the end of the script.

I hope this all makes sense! :slight_smile:

Yes it does make sense, thank you. I did notice the funny names, but I’d thought i’d just run it to see what it did. Thank you for holding the hand of a newbie. :smiley:

Dear Nigel,

All right… just what I was looking for!

Thanks for making life easier!