Help with renaming files in folders.

Hello

I have a bunch of folders that have several files in them. I am trying to get a script so it will prompt for a folder and remove all spaces and special characters, including spaces and underscores. I Would also like to have the cases changed to differentiate each word…

Eg. I have 1 folder that has 3 files in it, and the file names are (file 1) “BLACK & WHITE.PDF”, (file 2) “$40 SALE_Today.eps” (file 3) “BackGround_Image!.EPS”

those would be changed to the following names, BlackWhite.pdf, 40SaleToday.eps, BackgrounImage.eps

is this at all possible?

This seems to work well enough:

choose folder with prompt "Rename files in this folder:"
set sourceFolder to result
list folder result without invisibles

repeat with thisItem in result
	-- Skip folders
	folder of (info for alias ((sourceFolder as Unicode text) & thisItem))
	
	if not result then
		-- Escape double quotes
		set ASTID to AppleScript's text item delimiters
		set AppleScript's text item delimiters to {"\""}
		set escapedItem to text items of thisItem
		set AppleScript's text item delimiters to {"\\\""}
		set escapedItem to "" & escapedItem
		set AppleScript's text item delimiters to ASTID
		
		try
			-- Removes any characters, besides periods, that are not ASCII letters or digits
			do shell script "/usr/bin/ruby -e '\"" & escapedItem & "\".downcase.split(/[^a-zA-Z0-9\\.]/).each {|word| print word.capitalize}'"
			
			-- Rename the file
			tell application "Finder" to set name of item thisItem of sourceFolder to result
		on error errMsg number errNum
			display dialog "Error " & errNum & return & return & errMsg buttons {"Cancel Script", "Skip File"} default button 2
			if button returned of result is "Cancel Script" then error number -128 -- cancel
		end try
	end if
end repeat

May or may not be the most efficient way; It’s the first thing I could put together this late.

I left periods intact to make it easier to handle filename extensions. This means that names like “HELLO.WORLD.TXT” will come out as “Hello.world.txt”; If that is a problem, then you’ll have to do more work to handle it.

Hi, Bruce.

That’s great, though I found I had to escape single quotes too.

Here’s a slightly faster version that gets all the file names in one go and treats them as a single mass of text, using just one ‘do shell script’ call. For this, I had to experiment with your Ruby string to get it to pass my ‘return’ delimiter too. However, I found that it caused the initial character in all but the first name not to capitalise. I got round the problem by changing the delimiter to ‘return & space’, but is there a better way?

set sourceFolder to (choose folder with prompt "Rename files in this folder:")

-- Get the name of every *file* in the folder.
tell application "Finder" to set fileNames to name of every file of sourceFolder

set ASTID to AppleScript's text item delimiters
-- Coerce the names to a single, (return & space)-delimited text.
set AppleScript's text item delimiters to {return & space}
set escapedText to fileNames as Unicode text
-- Escape double and single quotes.
set AppleScript's text item delimiters to {"\""}
set escapedText to text items of escapedText
set AppleScript's text item delimiters to {"\\\""}
set escapedText to escapedText as Unicode text
set AppleScript's text item delimiters to {"'"}
set escapedText to text items of escapedText
set AppleScript's text item delimiters to {"'\\''"}
set escapedText to escapedText as Unicode text
set AppleScript's text item delimiters to ASTID

-- Remove any characters, besides periods and returns, that are not ASCII letters or digits; capitalise.
set newNames to paragraphs of (do shell script ("/usr/bin/ruby -e '\"" as Unicode text) & escapedText & "\".downcase.split(/[^a-zA-Z0-9\\.\\r]/).each {|word| print word.capitalize}'")

-- Rename the files.
repeat with i from 1 to (count fileNames)
	try
		tell application "Finder" to set name of file (item i of fileNames) of sourceFolder to item i of newNames
	on error errMsg number errNum
		display dialog "Error " & errNum & return & return & errMsg & return & (item i of fileNames) buttons {"Cancel Script", "Skip File"} default button 2
		if button returned of result is "Cancel Script" then error number -128 -- cancel
	end try
end repeat

Yeah, I missed that; Backslashes may need to be escaped too.

I was trying to think of a way to pass the names to Ruby through stdin, but I couldn’t decide which way, and (more importantly) I didn’t want to figure out any more Ruby. :stuck_out_tongue: (I was hoping to avoid the quoting problems this way, though now I don’t think it’s necessary.)

Offhand, I’m guessing that’s an issue with the capitialize method; I don’t know of a better way, but I will be giving this script another look.

Edit: Nigel, escapedItem is undefined in your error handling code.

This one gets the new names with one shell script and avoids the quoting issues.

choose folder with prompt "Rename files in this folder:"
set sourceFolder to POSIX path of result

do shell script "/bin/ls -p " & quoted form of sourceFolder & " | /usr/bin/grep -v '/$' | /usr/bin/tr ':' '/'"
set originalNames to paragraphs of result

do shell script "/bin/ls -p " & quoted form of sourceFolder & " | /usr/bin/grep -v '/$' | /usr/bin/ruby -e 'STDIN.readlines.each {|line| line.downcase.split(/[^a-zA-Z0-9\\.]/).each {|word| print word.capitalize}; print \"\\n\"}'"
set newNames to paragraphs of result

set sourceFolder to (sourceFolder as POSIX file) as alias
count originalNames

repeat with i from 1 to result
    try
        tell application "Finder" to set name of file (item i of originalNames) of sourceFolder to (item i of newNames)
    on error errMsg number errNum
        display dialog "Error " & errNum & return & return & errMsg buttons {"Cancel Script", "Skip File"} default button 2
        if button returned of result is "Cancel Script" then error number -128 -- cancel
    end try
end repeat

Side note: In case anyone’s interested, here’s the expanded style of the above ruby script:

STDIN.readlines.each do |line| line.downcase.split(/[^a-zA-Z0-9\.]/).each do |word| print word.capitalize end print "\n" end

Ah. Thanks, Bruce. I stuck it in to find out which files were causing the errors when I tried your original script, which is how I came across the need to escape single quotes too. I forgot to change it when I modified the script. I’ve now edited it in my post above.

Your second version seems to work well, except that it trips up on file names that contain forward slashes, which are still possible “ albeit frowned upon “ in Mac OS X. The “ls” shell script returns these names with colons instead of slashes and the Finder can’t cope with them when it comes to rename the files.

Ah, I missed that; I’ve edited my second script above to handle this (via tr).