Hi Folks,
I have a script here that works just fine, but I’d like it to be a folder action that I can attach to a folder so that filenames are changed as they are added to the folder (volume). I do not know how to do this though, can someone provide direction? -thanks, dan
here is script, it simply removes underscores:
set defDel to AppleScript’s text item delimiters
tell application “Finder”
set theFolder to folder (choose folder)
repeat with thisItem in theFolder
set thename to name of thisItem
if thename contains “" then
set AppleScript’s text item delimiters to "”
set newName to text items of thename
set AppleScript’s text item delimiters to “”
set name of thisItem to (newName as string)
set AppleScript’s text item delimiters to defDel
end if
end repeat
end tell
on adding folder items to this_folder after receiving added_items
set defDel to AppleScript's text item delimiters
tell application "System Events"
if type identifier of (item 1 of added_items) is "public.folder" then
set added_items to added_items & disk items of (item 1 of added_items)
end if
repeat with thisItem in added_items
try
if visible of thisItem then
set thename to name of thisItem --disk item thisItem
if thename contains "_" then
set AppleScript's text item delimiters to "_"
set newName to text items of thename
set AppleScript's text item delimiters to ""
set name of thisItem to (newName as string)
end if
end if
end try
end repeat
end tell
set AppleScript's text item delimiters to defDel
end adding folder items to
Thanks for the feedback.
I’m not fully satisfied by the posted code.
I’m quite sure that there is a way to clean it a bit but at this time I’m switching between four tasks:rolleyes:
One thing I am not accomplishing here is that when a renamed file matches that of an existing file, the old file is not replaced by the new but that is what I’d like to have happen. Any ideas on how this can be integrated into this script?
-dan
AppleScript: 2.4.3
Browser: Safari 537.36
Operating System: Mac OS X (10.7)
It’s a bit boring to be given elements of the question one after the other. Is it so difficult to think a bit before asking so that the question describe precisely and completely what is needed. As far as I know, macScripter is not a forum of soothsayers.
Your original question was only about renaming the files embedded in the selected folder.
Must I understand that this folder may contain files whose modified name would be identical to already existing files ?
example : the dropped folder is named share and contain the files :
.share:ab_cd_ef
.share:abcdef
Must I understand too that if you drop a folder whose name contain underscores, it must replace an other folder whose name matches the new one deprived of underscores ?
example: the folder to which the script is attached contains a folder named share1 and the dropped folder is named share_1 This was not part of the original question.
Yvan, I appreciate the wry, peeved humor and don’t mean to drag you around. I am in the dark enough that I didn’t even realize I’d need to account for this.
It is true, that a newly renamed file must replace another file whose name matches the new one deprived of underscores and this is the ultimate goal. The items that would land at the destination would be files only, not folders and the destination is a folder on a server that is shared out as a volume. The script runs on the server’s system. Hopefully there are no other unseen surprises.
You asked for a folder action.
This tool is triggered when we drop items onto the folder to which it is attached.
To achieve what you describe, we don’t have to drag and drop a folder onto the folder to which the script is attached, we must drag and drop the group of files.
An alternative would be to drag and drop a folder so that the script would rename the items embedded in the dropped folder then execute a move with replacing action for every file. then, at last it would delete the folder.
To achieve this task, it would be useful to know if the items may be folders or packages.
Worse, as I never use servers, I don’t know if a script may be attached to a folder stored on a network.
The server is a macOS server and a folder on that server that is shared receives files (only) across the network from another server. I am operating the script from there so to the system, it is a local directory. The destination folder may receive the same file multiple times as it is revised. On the destination, we only want one copy of it, the newest. If I could control the file naming coming from the other system, I would not need this at all. The removal of the underscore is the goal. I did not anticipate the overwrite issue.
-dan
For me the fact that the server is a macOS Server makes no difference, I’ve no experience with them.
The script below was tested with a folder stored on a local device.
You may drop a folder or a group of files on the folder to which it is attached.
on adding folder items to this_folder after receiving added_items
# underscore in varName of class file, folder or alias
local maybe_Folder, added_items, this_Item
# no underscore in varName of class boolean , text or list of text items
local thisFolder, qpFolder, defDel, droppedAfolder, droppedFolder, listToMove, thisItem, thename, nameAsList
set thisFolder to this_folder as text
set qpFolder to quoted form of (POSIX path of this_folder)
set defDel to AppleScript's text item delimiters
set droppedAfolder to false
set maybe_Folder to contents of (item 1 of added_items)
tell application "System Events"
if type identifier of maybe_Folder is "public.folder" then
set droppedAfolder to true
set added_items to disk items of maybeFolder
set droppedFolder to maybe_Folder as text
end if
if droppedAfolder then
set listToMove to {}
repeat with this_Item in added_items
try
set thisItem to path of this_Item
set thename to name of this_Item
if visible of this_Item then
if thename contains "_" then
set AppleScript's text item delimiters to "_"
set nameAsList to text items of thename
set AppleScript's text item delimiters to ""
set thename to nameAsList as string
set name of this_Item to thename
set thisItem to droppedFolder & thename
end if # thename contains "_"
if exists disk item thename of this_folder then delete disk item (thisFolder & thename)
set end of listToMove to my getQuotedPosixPath(thisItem)
end if
end try
end repeat
if listToMove ≠{} then
set listToMove to my recolle(listToMove, space)
tell me to do shell script "mv " & listToMove & space & qpFolder
end if
delete maybe_Folder
else
# The first item of the list of dropped items is not a folder
repeat with this_Item in added_items
try
set thisItem to path of this_Item
set thename to name of this_Item
if visible of this_Item then
if thename contains "_" then
set AppleScript's text item delimiters to "_"
set nameAsList to text items of thename
set AppleScript's text item delimiters to ""
set thename to nameAsList as string
if exists disk item thename of this_folder then
delete disk item (thisFolder & thename)
delay 0.2
end if
set name of this_Item to thename
end if # thename contains "_"
end if # visible of thisItem
end try
end repeat
end if # droppedAfolder
end tell # System Events
set AppleScript's text item delimiters to defDel
end adding folder items to
#=====
on getQuotedPosixPath(anItem)
return quoted form of POSIX path of anItem
end getQuotedPosixPath
#=====
on recolle(l, d)
local oTIDs, t
set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
set t to l as text
set AppleScript's text item delimiters to oTIDs
return t
end recolle
#=====
Here is a version using several ASObjC functions.
Maybe I will rework it to drop completely System Events.
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
on adding folder items to this_folder after receiving added_items
# underscore in varName of class file, folder or alias
local maybe_Folder, added_items, this_Item
# no underscore in varName of class boolean , text or list of text items
local thisFolder, qpFolder, defDel, droppedAfolder, droppedFolder, listToMove, thisItem, thename, nameAsList
(*
set this_folder to ((path to desktop as text) & "Share:") as alias
set added_items to {((path to desktop as text) & "Share:some items copie:") as alias}
*)
set thisFolder to this_folder as text
set droppedAfolder to false
set maybe_Folder to contents of (item 1 of added_items)
tell application "System Events"
if type identifier of maybe_Folder is "public.folder" then
set droppedAfolder to true
set added_items to disk items of maybe_Folder whose visible is true
set droppedFolder to maybe_Folder as text
end if
if droppedAfolder then
set listToMove to {}
repeat with this_Item in added_items
try
set thisItem to path of this_Item
set thename to name of this_Item
if visible of this_Item then
if thename contains "_" then
set thename to (my replace:thename existingString:"_" newString:"")
set name of this_Item to thename
set thisItem to droppedFolder & thename
end if # thename contains "_"
(my moveThis:(thisItem) toThisItem:(thisFolder & thename))
end if
end try
end repeat
delete folder droppedFolder
else
# The first item of the list of dropped items is not a folder
repeat with this_Item in added_items
try
set thisItem to path of this_Item
set thename to name of this_Item
if visible of this_Item then
if thename contains "_" then
set thename to (my replace:thename existingString:"_" newString:"")
(my deleteIfExists:(thisFolder & thename))
set name of this_Item to thename
end if # thename contains "_"
end if # visible of thisItem
end try
end repeat
end if # droppedAfolder
end tell # System Events
end adding folder items to
#=====
on replace:sourceString existingString:d1 newString:d2
set sourceString to current application's NSString's stringWithString:sourceString
return (sourceString's stringByReplacingOccurrencesOfString:d1 withString:d2) as text
end replace:existingString:newString:
#=====
on deleteIfExists:HFSpath
set POSIXPath to POSIX path of HFSpath
set FileManager to current application's NSFileManager's defaultManager --> <NSFileManager: 0x7f8581603da0>
set FileExists to FileManager's fileExistsAtPath:POSIXPath
if FileExists then set WasSucessful to FileManager's removeItemAtPath:POSIXPath |error|:(missing value)
end deleteIfExists:
#=====
on moveThis:HFSpath toThisItem:HFSNewItem
set POSIXPath to POSIX path of HFSpath
set POSIXNewItem to POSIX path of HFSNewItem
set FileManager to current application's NSFileManager's defaultManager --> <NSFileManager: 0x7f8581603da0>
set FileExists to FileManager's fileExistsAtPath:POSIXNewItem
if FileExists then set WasSucessful to FileManager's removeItemAtPath:POSIXNewItem |error|:(missing value)
set WasSucessful to FileManager's moveItemAtPath:POSIXPath toPath:POSIXNewItem |error|:(missing value)
if (not WasSucessful) then
display dialog "Could not move the file "" & POSIXPath & ""." buttons {"Cancel", "OK"} default button "OK"
return false
end if
end moveThis:toThisItem:
#====
CAUTION: As both versions use POSIX and HFS path they would fail if the HFS filenames contain slashes.
Here is a version using neither Finder nor System Events.
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
on adding folder items to this_folder after receiving added_items
# underscore in varName of class file, folder or alias
local added_items, this_Item
# no underscore in varName of class boolean , text or list of text items
local POSIXFolder, droppedPOSIXFolder, FileManager, FileAttributes, droppedAfolder, added_names, aName
local NSPOSIXItem, NSNewPOSIXPath, NSPOSIXOrig, NSPOSIXMoved, theResult, theError
(*
# Used during tests to mimic passed datas.
set thisFolder to ((path to desktop as text) & "parent:")
set this_folder to thisFolder as alias
set added_items to {(thisFolder & "DSC_0049.jpg") as alias, (thisFolder & "Position_01:") as alias}
-- set added_items to {(thisFolder & "parent copie:") as alias}
*)
# As passed datas are Hfs aliases, every folder path ends with a colon
set POSIXFolder to POSIX path of this_folder # with an ending slash
set droppedPOSIXFolder to POSIX path of (item 1 of added_items) # with an ending slash
set FileManager to current application's NSFileManager's defaultManager
set FileAttributes to FileManager's attributesOfItemAtPath:droppedPOSIXFolder |error|:(missing value)
set droppedAfolder to (FileAttributes's objectForKey:(current application's NSFileType)) as text is "NSFileTypeDirectory"
if droppedAfolder then
# Build a list of "posix" names: if the Hfs name contains a slash, in the "posix" name it's replaced by a colon
set added_names to (FileManager's contentsOfDirectoryAtPath:droppedPOSIXFolder |error|:(missing value)) as list
repeat with aName in added_names
if aName does not start with "." then
try
set NSPOSIXItem to (current application's NSString's stringWithString:(droppedPOSIXFolder & aName))
if aName contains "_" then
# Builds the new name
set aName to (my replace:aName existingString:"_" newString:"")
set NSNewPOSIXPath to (current application's NSString's stringWithString:(droppedPOSIXFolder & aName))
# Rename the file. Here both paths MUST be NSStrings
set {theResult, theError} to (FileManager's moveItemAtPath:NSPOSIXItem toPath:NSNewPOSIXPath |error|:(reference))
copy NSNewPOSIXPath to NSPOSIXOrig
else
copy NSPOSIXItem to NSPOSIXOrig
end if # thename contains "_"
# Builds the path to the moved item
set NSPOSIXMoved to (current application's NSString's stringWithString:(POSIXFolder & aName))
# If there is already an item with the given name, delete it.
# The given path may be a POSIX path or an NSString built upon a POSIX path (what it's here)
if (FileManager's fileExistsAtPath:NSPOSIXMoved) then
set theResult to (FileManager's removeItemAtPath:NSPOSIXMoved |error|:(missing value))
end if
# Move the item. Here both paths MUST be NSStrings
set {theResult, theError} to (FileManager's moveItemAtPath:NSPOSIXOrig toPath:NSPOSIXMoved |error|:(reference))
end try
end if
end repeat
# Delete the dropped folder. The give path may be a POSIX path (what it's here) or an NSString built upon a POSIX path
set theResult to FileManager's removeItemAtPath:droppedPOSIXFolder |error|:(missing value)
else
# The first item of the list of dropped items is not a folder
repeat with this_Item in added_items
try
set NSPOSIXItem to (current application's NSString's stringWithString:(POSIX path of this_Item))
set aName to NSPOSIXItem's lastPathComponent() as text
if aName does not start with "." then
if aName contains "_" then
set aName to (my replace:aName existingString:"_" newString:"")
set NSNewPOSIXPath to (current application's NSString's stringWithString:(POSIXFolder & aName))
# If there is already an item with the new name, delete it
if (FileManager's fileExistsAtPath:NSNewPOSIXPath) then
set theResult to (FileManager's removeItemAtPath:NSNewPOSIXPath |error|:(missing value))
end if
# Rename the file
set {theResult, theError} to (FileManager's moveItemAtPath:NSPOSIXItem toPath:NSNewPOSIXPath |error|:(reference))
end if # aName contains "_"
end if # visible of POSIXItem
end try
end repeat
end if # droppedAfolder
end adding folder items to
#=====
on replace:sourceString existingString:d1 newString:d2
set sourceString to current application's NSString's stringWithString:sourceString
return (sourceString's stringByReplacingOccurrencesOfString:d1 withString:d2) as text
end replace:existingString:newString:
#=====
Thank you Yvan,
Yes, an enjoyable Christmas - likewise.
Thanks for your extensive work on this - it is actually beyond my understanding but I now have a script that is doing exactly what I need it to: changing the names of files that I can’t control at their creation and replacing the files with the undesired names.
Best, Dan
I am using the version from 2016-12-23 01:48:34 pm. Have not had a chance to test/try the “Foundation” versions yet. Will let you know if I do. Happy New Year, Dan