Folder action: unwanted re-triggering after changing file name

Dear all,

I have an attached script (Folder action) to the Downloads folder. Every downloaded file get renamed based on a complicate scheme.
But to simplify let’s say I have a script like this

on adding folder items to this_folder after receiving dropped_items -- this_folder is an alias
	repeat with alias_ref in dropped_items
		tell application "Finder"
			set myFileName to alias_ref's name
			set alias_ref's name to (myFileName & "_1")
		end tell
	end repeat
end adding folder items to

The problem I would like to solve is that when the script change the name of the file, the folder action script get re-triggered again… and again …
Is there any simply way to circumvent this without moving the file to a different location?

Very old behavior.

To get rid of that, don’t rename the objects in the hot folder itself but in an other folder which may be inside the hot folder or outside of it.

on adding folder items to this_folder after receiving dropped_items -- this_folder is an alias
	tell application "Finder" # MOVED
		set storageName to "safeFolder"
		set storagePath to (this_folder as text) & storageName
		if not (exists folder storagePath) then
			# At first attempt,the new folder will be created so as it is
			# in the hot folder this one will be triggered again.
			make new folder at this_folder with properties {name:storageName}
		end if
		repeat with alias_ref in dropped_items
			set myFileName to alias_ref's name
			set newLoc to move alias_ref to folder storagePath
			set newLoc's name to (myFileName & "_1")
		end repeat
	end tell # Moved
end adding folder items to

But this script would return files named as trucmuche.rtf_1 which is odd.

Better to use :

on adding folder items to this_folder after receiving dropped_items -- this_folder is an alias
	tell application "Finder" # MOVED
		set storageName to "safeFolder"
		set storagePath to (this_folder as text) & storageName
		if not (exists folder storagePath) then
			# At first attempt,the new folder will be created so as it is
			# in the hot folder this one will be triggered again.
			make new folder at this_folder with properties {name:storageName}
		end if
		repeat with alias_ref in dropped_items
			set myFileName to alias_ref's name
			set theExt to name extension of alias_ref
			if theExt is not "" then
				set bareName to text 1 thru -(2 + (count theExt)) of myFileName
				set suffix to "."
			else
				set bareName to myFileName
				set suffix to ""
			end if
			set newLoc to move alias_ref to folder storagePath
			set newLoc's name to (bareName & "_1" & suffix & theExt)
		end repeat
	end tell # Moved
end adding folder items to

It would be easy to edit the script if you decide to store the renamed fils in a bolder outside of the hot folder.

PS. No time to check but, if my memory is OK, when we enter such a script, we are already ‘telling’ to the Finder so the instruction tell application “Finder” is not required.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 21 décembre 2019 14:26:35

Thanks Yvan.
I was hoping for a solution without moving the file, but I guess is impossible.
You idea of a subfolder might actually works for me.

Thanks !
L.

No need move the items to other location. Try this:


on adding folder items to this_folder after receiving dropped_items
	tell application "Finder"
		repeat with alias_ref in dropped_items
			
			set {aName, anExt} to {alias_ref's name, alias_ref's name extension}
			if not (aName contains "_") then
				if anExt is not "" then
					set baseName to text 1 thru -(2 + (count anExt)) of aName
					set alias_ref's name to (baseName & "_1." & anExt)
				else
					set alias_ref's name to (aName & "_1")
				end if
			end if
			
		end repeat
	end tell
end adding folder items to

NOTE: you will get safer results if you attach some tag (as “isRenamed”). Then in if statement you should check if the item has this tag or not.

Are you sure that it works?

As far as I remember, renaming the item in the hot folder itself push this hot folder to ‘think’ that it received new items.
But maybe something changed with recent systems.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 21 décembre 2019 20:45:38

KniazidisR

Don’t be so nervous.
I missed the test upon the availability of a “_” in pathnames of items dropped but I was right.

Try to drop a file whose name contains a “_” on a folder with your script attached.
I create files with such name several times a day.
The script will not rename the file.

Of course you may get rid of such case in most of thefiles if you replace your test upon “_” by a test upon “_1.” but
1 - you didn’t
2 - as far as I know, it’s not forbidden to create a file named “azerty_1.qwerty.txt” and drop it upon a hot folder.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 21 décembre 2019 21:10:30

Use Finder tags if you don’t like my code so much. You mislead users and this is not good.

Funny reaction. Be quiet.

Honestly, I don’t think that I posted “3737 worthless posts”. You may count the number of threads in which my answer were helpful.

Sometimes, as in https://macscripter.net/viewtopic.php?id=47284 I post numerous messages because I am unable to test what I built.
In such case, I remove the contents of ‘finally useless’ messages just to take care not to waste space in storage areas.
When the final script will be ready, I will ask ChangeAgent to delete ‘no longer useful’ messages and will delete mine too.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 21 décembre 2019 21:42:18

ldicroce

If you are sure that you will never drop files whose name contain the substring “_1.”, you may use the script posted by KniazidisR after editing one instruction:
Replace

 if not (aName contains "_") then

by

 if not (aName contains "_1.") then

With such change, the script will behave this way :

1- receive a file named “azerty qwerty.txt”
2 - rename it as “azerty qwerty_1.txt”
3 - warn the system that the folder has ‘received’ the file renamed as “azerty qwerty_1.txt”
4 - will not rename it.
So you will get the wanted result with a script working more than necessary.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 21 décembre 2019 21:59:54

I asked to delete your post above, but you did not. As I said, you don’t need to stamp immediately that the code does not work.

I am always interested in the idea. The final implementation interests me too, although less. If you made amendments, and did not say that the idea does not work at all, my reaction would not be so nervous.

And, my script is still here

KniazidisR

Your script behaves this way :

1 - receive a file named “azerty qwerty.txt”
2 - rename it as “azerty qwerty_1.txt”
after that it :
3 - warn the system that the folder has ‘received’ the file renamed as “azerty qwerty_1.txt”
4 - will not rename it.

So, it gives the final result but it doesn’t avoid “unwanted re-triggering after changing file name” which is the original question. It just avoid an unwanted renaming :rolleyes:

Have a good night. On my side it’s time to sleep.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 21 décembre 2019 22:15:58

The 4 steps is named idea. The script doesn’t just avoid an unwanted renaming. It works, as OP asked and that is all.

Good night to you too. I apologize for overreacting about the posts.

Final implementation of the script. With better approach - using Finder tags:


use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
property NSArray : a reference to NSArray of current application
property |NSURL| : a reference to NSURL of current application
property NSURLTagNamesKey : a reference to NSURLTagNamesKey of current application

on adding folder items to this_folder after receiving dropped_items
	tell application "Finder"
		set tagArray to (NSArray's arrayWithArray:{"isRenamed"})
		repeat with alias_ref in dropped_items
			
			set {aName, anExt} to {alias_ref's name, alias_ref's name extension}
			set aPath to POSIX path of alias_ref
			set anURL to (|NSURL|'s fileURLWithPath:aPath)
			
			-- Read the Finder tags of the current Finder item
			set {theResult, theTags} to (anURL's getResourceValue:(specifier) ¬
				forKey:(current application's NSURLTagNamesKey) |error|:(missing value))
			set theTagsList to theTags as list
			
			-- Check, if the current Finder item is not renamed
			if not (theTagsList is {"isRenamed"}) then
				-- Set Current Finder item's tags list to {"isRenamed"}
				(anURL's setResourceValue:tagArray forKey:NSURLTagNamesKey |error|:(missing value))
				if anExt is not "" then
					set baseName to text 1 thru -(2 + (count anExt)) of aName
					set alias_ref's name to (baseName & "_1." & anExt)
				else
					set alias_ref's name to (aName & "_1")
				end if
			end if
			
		end repeat
	end tell
end adding folder items to

Below is your script with 5 added instructions allowing us to check that it behaves as I wrote.


use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
property NSArray : a reference to NSArray of current application
property |NSURL| : a reference to NSURL of current application
property NSURLTagNamesKey : a reference to NSURLTagNamesKey of current application

on adding folder items to this_folder after receiving dropped_items
	tell application "Finder"
		set tagArray to (NSArray's arrayWithArray:{"isRenamed"})
		repeat with alias_ref in dropped_items
			set {aName, anExt} to {alias_ref's name, alias_ref's name extension}

			if aName contains "_1" then # ADDED
				tell me to say "received file named : " & aName & " which was previously renamed" # ADDED
			else # ADDED
				tell me to say "received file named : " & aName # ADDED
			end if # ADDED

			set aPath to POSIX path of alias_ref
			set anURL to (|NSURL|'s fileURLWithPath:aPath)
			
			-- Read the Finder tags of the current Finder item
			set {theResult, theTags} to (anURL's getResourceValue:(specifier) ¬
				forKey:(current application's NSURLTagNamesKey) |error|:(missing value))
			set theTagsList to theTags as list
			
			-- Check, if the current Finder item is not renamed
			if not (theTagsList is {"isRenamed"}) then
				-- Set Current Finder item's tags list to {"isRenamed"}
				(anURL's setResourceValue:tagArray forKey:NSURLTagNamesKey |error|:(missing value))
				if anExt is not "" then
					set baseName to text 1 thru -(2 + (count anExt)) of aName
					set alias_ref's name to (baseName & "_1." & anExt)
				else
					set alias_ref's name to (aName & "_1")
				end if
			end if
			
		end repeat
	end tell
end adding folder items to

When we drop a file on it, we hear:

“received file named : azerty qwerty.txt”
then we hear:
“received file named : azerty qwerty_1.txt which was previously renamed”

It’s logical because your script does exactly what I wrote:

1 - receive a file named “azerty qwerty.txt”
2 - rename it as “azerty qwerty_1.txt”
after that it :
3 - warn the system that the folder has ‘received’ the file renamed as “azerty qwerty_1.txt”
4 - will not rename it.

One ‘unwanted re-triggering after changing file nameis always issued.
We no longer have : ‘the folder action script get re-triggered again… and again …
We have : ‘the folder action script get re-triggered again

With the script moving the file in an auxiliary folder,
we get a similar behavior if the subfolder is not available at first use because the system is warned that a folder named “safeFolder” has been ‘added’ to it.
No such warning is issued if the subfolder was created before first use.
When the subfolder exists, we no longer have the ‘unwanted re-triggering’.
We just have:
1 - receive a file named “azerty qwerty.txt”
2 - move it in “safeFolder”
2 - rename the moved file as “azerty qwerty_1.txt”.
So we really don’t issue ‘unwanted re-triggering after changing file name

I may understand that you dislike to read this truth, but, believe it or not, it’s the truth.
I may also understand that the fact that your script doesn’t require a subfolder may be seen as a valid alternative to this use.
I would be glad to read ldicroce’s opinion about that.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) dimanche 22 décembre 2019 10:08:44

dear Yvan and KniazidisR,

thanks for the contributing to this.
I like a lot the idea of using tag/subfolder for avoiding further cycles of re-triggering.
I didn’t thought about that.
Thanks !

I am editing this post after reading Yvan’s comment #14.
I have to admit that both options are valid, and technically speaking Yvan’s solve the retriggering problem from the starting.
But moving files in a subfolder is not optimal for the setting I have (the Downloads folders of all my Macs get synchronised with a complicated scheme (combination of Symbolic Link-DropBox-iCloud). And a sub-folder will not be as easy ti implement initially.
I will in any case explore and test both options knowing that both are good and solve the problem i posed.
Thanks again to both!

Thank you ldicroce

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) dimanche 22 décembre 2019 11:31:16

So, Yvan Koenig is again dissatisfied with us… The second retriggering, blabla and so on. Well, I have enough that I am completely satisfied with my work. I mean my last brilliant script.

ldicroce

If you are satisfied with the KniazidisR’s version triggering the script twice, here is an enhanced version.
When it receive a file, it rename it and give it the “isRenamed” tag.
This force the system to trigger the script one more time.
At this time the received file is tagged, there is no need to rename it but it’s time to remove the tag which is no longer needed.
I made a small change because there is no need to explicitly convert a tag list into an array.

The original script is replaced by the enhanced one - preserving existing tags - available in message #20.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) lundi 23 décembre 2019 12:44:06

Thanks! I like the improvement !
Taking advantage of the re-triggering for cleaning the tag is a cool idea.
Ciao
L.

Are you sure that the dropped files have no tags or is it useful to rework the code so that it preserve existing tags in both steps ?

Here is the ‘enhanced’ version

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
property |NSURL| : a reference to NSURL of current application
property NSURLTagNamesKey : a reference to NSURLTagNamesKey of current application

on adding folder items to this_folder after receiving dropped_items
	-- two instructions used to test the code
	--set this_folder to ((path to desktop as text) & "chaud:") as alias
	--set dropped_items to {((path to desktop as text) & "chaud:jezebel_1.png") as alias}
	set isRenamed to "isRenamed"
	tell application "Finder"
		repeat with alias_ref in dropped_items
			set {aName, anExt} to {alias_ref's name, alias_ref's name extension}
			set aPath to POSIX path of alias_ref
			set anURL to (|NSURL|'s fileURLWithPath:aPath)
			
			-- Read the tags of the current Finder item
			set {theResult, theTags} to (anURL's getResourceValue:(specifier) ¬
				forKey:NSURLTagNamesKey |error|:(missing value)) # EDITED
			if theTags is missing value then # ADDED
				set theTagList to {} # ADDED
			else # ADDED
				set theTagsList to theTags as list
			end if # ADDED
			-- Check, if the current Finder item was renamed
			if theTagsList contains isRenamed then # EDITED
				set originalTags to {}
				repeat with aTag in theTagsList
					if aTag as text is not isRenamed then set end of originalTags to aTag
				end repeat
				# The unwanted re-triggering bring us here.
				# Remove the added tag which is no longer needed
				(anURL's setResourceValue:originalTags forKey:NSURLTagNamesKey |error|:(missing value)) # ADDED
			else
				# As the file was not tagged as renamed, the first triggering bring us here
				set end of theTagsList to isRenamed
				# Append isRenamed to possible existing tags
				(anURL's setResourceValue:theTagsList forKey:NSURLTagNamesKey |error|:(missing value))
				if anExt is not "" then
					text 1 thru -(2 + (count anExt)) of aName # EDITED
					set alias_ref's name to (result & "_1." & anExt) # EDITED
				else
					set alias_ref's name to (aName & "_1")
				end if
			end if
		end repeat
	end tell
end adding folder items to

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) lundi 23 décembre 2019 15:13:57