I often use find and replace to rename files, and wondered if the way I’m doing it is the best (cleanest, most efficient) way of doing it.
Here’s an example of the kind of script I use often for renaming files.
tell application "Finder"
set fileList to selection as alias list
repeat with thisFile in fileList
set fileName to name of thisFile
set AppleScript's text item delimiters to "this"
set replaceTextItem to every text item of fileName
set AppleScript's text item delimiters to "that"
set fileName to replaceTextItem as string
set AppleScript's text item delimiters to ""
set AppleScript's text item delimiters to "ying"
set replaceTextItem to every text item of fileName
set AppleScript's text item delimiters to "yang"
set fileName to replaceTextItem as string
set AppleScript's text item delimiters to ""
set AppleScript's text item delimiters to "one"
set replaceTextItem to every text item of fileName
set AppleScript's text item delimiters to "two"
set fileName to replaceTextItem as string
set AppleScript's text item delimiters to ""
set AppleScript's text item delimiters to "white"
set replaceTextItem to every text item of fileName
set AppleScript's text item delimiters to "black"
set fileName to replaceTextItem as string
set AppleScript's text item delimiters to ""
set the name of thisFile to fileName
end repeat
end tell
Is this how is should be done, or is there a better way?
At least you could define a handler to avoid repetitive code
on findAndReplaceText(theText, find, replace)
set TID to text item delimiters
set text item delimiters to find
set textItems to text items of theText
if (count textItems) = 1 then -- nothing found, don't change anything
set text item delimiters to TID
return theText
else
set text item delimiters to replace
set newText to textItems as text
set text item delimiters to TID
return newText
end if
end findAndReplaceText
Then you can reduce your code (I made a few improvements)
tell application "Finder" to set fileList to selection
if fileList is {} then return
repeat with thisFile in fileList
set fileName to name of thisFile
set fileName to findAndReplaceText(fileName, "this", "that")
set fileName to findAndReplaceText(fileName, "ying", "yang")
set fileName to findAndReplaceText(fileName, "one", "two")
set fileName to findAndReplaceText(fileName, "white", "black")
tell application "Finder" to set the name of thisFile to fileName
end repeat
An alternative handler is the AppleScriptObjC Foundation way to find and replace text
use framework "Foundation"
on findAndReplaceText(theText, find, replace)
set foundationString to current application's NSString's stringWithString:theText
return (foundationString's stringByReplacingOccurrencesOfString:find withString:replace) as text
end findAndReplaceText
Thanks a lot! I thought (hoped) there must be way streamline it and make it less repetitive.
The second one works fine, but the first one throws up an error
tell application "Script Editor"
count every text item of current application
--> error number -1728
Result:
error "Can’t get every text item of «script»." number -1728 from every text item
If I use it like this:
tell application "Finder" to set fileList to selection
if fileList is {} then return
repeat with thisFile in fileList
set fileName to name of thisFile
log fileName
set fileName to findAndReplaceText(fileName, "this", "that")
set fileName to findAndReplaceText(fileName, "ying", "yang")
set fileName to findAndReplaceText(fileName, "one", "two")
set fileName to findAndReplaceText(fileName, "white", "black")
tell application "Finder" to set the name of thisFile to fileName
end repeat
on findAndReplaceText(theText, find, replace)
set TID to text item delimiters
set text item delimiters to find
set textItems to text items of theText
if (count text items) = 1 then -- nothing found, don't change anything
set text item delimiters to TID
return theText
else
set text item delimiters to replace
set newText to textItems as text
set text item delimiters to TID
return newText
end if
end findAndReplaceText