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