Convert script to folder action

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

You may try:

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

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mercredi 21 décembre 2016 16:04:22

Yvan,
Thank you for your reply, this is working fine and I have learned something.
Merci, Dan

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:

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mercredi 21 décembre 2016 17:09:47

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 KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) vendredi 23 décembre 2016 14:55:36

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.

best, dan

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.

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) vendredi 23 décembre 2016 17:59:12

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

#=====

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) vendredi 23 décembre 2016 19:48:13

wow. wouah.
I look forward to trying this out. Thanks very much for sharing your depth of knowledge. Will post on return to work next week.
-dan

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.

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) dimanche 25 décembre 2016 20:50:24

I hope that you all had a Merry Christmas.

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:

#=====

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) lundi 26 décembre 2016 18:43:34

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

Thanks for the feedback.
Which version are you using?
Knowing it I will comment it to help you to understand what it does.

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mercredi 28 décembre 2016 15:09:41

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