Applescript: Adding a custom tag to a selected file in Finder

Hello, im new to any kind of scripting (including AppleScript) but was attempting to make a simple script that would add a CUSTOM (TEXT) TAG in finder to a CURRENTLY SELECTED (HIGHLIGHTED) FILE


I tried some of the scripts/suggestions on these links ..


https://discussions.apple.com/thread/8395577

https://stackoverflow.com/questions/19784075/modifying-file-tags-with-applescript

https://discussions.apple.com/thread/8267280


but couldn't get them to work (or i haven't fully understood them to make them work as intended) - am wanting to run through Dictate so that I can say, for example, "tag photo" and the Apple script will then tag the selected file with the custom tag, 'photo'


Appreciate any help! Thanks. Dan

Posted on May 27, 2021 3:07 AM

Reply
Question marked as Top-ranking reply

Posted on May 29, 2021 10:03 AM

I have a Voice Dictation command "Tag Photo" working with an AppleScript that sets the "Photo" tag on selected filesystem objects. The AppleScript is written so you only need to make one change with each script and that is to change the TAG_NAME properties tag string. If a filesystem object already has a tag name on it, the script will add your tag name to that file or folder.


Here is the AppleScript that you copy/paste into Script Editor (Launchpad > Other > Script Editor). You then click the compile button, and save it twice: 1) as a text format tagname_photo.applescript in your preferred location, and then with option+Save As as a script format tagname_photo.scpt in /Users/yourname/Library/Scripts/Applications/Finder folder. The latter is where you will tell your new Voice Control command to find the workflow…


The AppleScript:


(*
AppleScript that checks selected filesystem obect(s) for existing tags
and adds the current tag name defined in the property beginning with TAG_

This script does not gather all defined tag names and attempt to validate
the user supplied tag name.

The user changes *one* location <== EDIT ==> for different tag name strings

Reference: https://discussions.apple.com/thread/252807460
Tested: macOS 11.4
VikingOSX, 2021-05-29, Apple Support Communities, No warranties expressed/implied
*)

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Cocoa"
use scripting additions

property NSUTF8StringEncoding : a reference to 4
property NSString : a reference to current application's NSString

property NSWorkspace : a reference to current application's NSWorkspace
property NSURL : a reference to current application's NSURL
property NSArray : a reference to current application's NSArray
property NSURLTagNamesKey : a reference to current application's NSURLTagNamesKey
property NSDictionary : a reference to current application's NSDictionary

property TAG_NAME : {"Photo"} # <== EDIT ==>

# assumption is that the filesystem object(s) are already selected before this
# script is invoked by Dictation.
set tagFileList to {}

# process selected items
tell application "Finder"
	if selection is {} then return
	set selList to selection
	repeat with anItem in selList
		copy POSIX path of (anItem as text) to the end of tagFileList
	end repeat
end tell

repeat with anItem in tagFileList
	my set_tag(anItem, TAG_NAME)
end repeat
return

on set_tag(theFile, atag)
	-- atag is always a list, even if single tag element
	-- place single, or multiple tags from atag on the specified file
	set existingTags to {}
	set tagArray to (NSArray's arrayWithArray:atag)'s mutableCopy()
	set existingTags to my file_tags(theFile)
	if (count of existingTags) ≥ 1 then
		# add the detected tag(s) to the existing TAG_NAME list item
		tagArray's addObjectsFromArray:existingTags
	end if
	
	set fileURL to NSURL's fileURLWithPath:theFile
	fileURL's setResourceValue:tagArray forKey:NSURLTagNamesKey |error|:(missing value)
	return
end set_tag

on file_tags(apath)
	-- Get all tags from the file, or an empty list if none
	-- apath = POSIX path to file
	set metadata to NSDictionary's dictionary()
	set aurl to NSURL's fileURLWithPath:apath
	set metadata to aurl's resourceValuesForKeys:{NSURLTagNamesKey} |error|:(missing value)
	-- file has no tags yet
	if (metadata's objectForKey:{NSURLTagNamesKey}) is missing value then return {""} as list
	-- file has tags, so return them as a list
	return (metadata's objectForKey:NSURLTagNamesKey) as list
end file_tags


In Accessibility > Voice Control > Commands… create your new command with the [+] button, and configure as follows. For testing purposes, I did not save the script as tagname_photo.scpt, but you should. And each variation of that script to match the voice command tag name should follow that format of the tag name in the filename.



Make certain that your file(s) are selected before speaking your voice command to trigger the script.

11 replies
Question marked as Top-ranking reply

May 29, 2021 10:03 AM in response to danielardeer

I have a Voice Dictation command "Tag Photo" working with an AppleScript that sets the "Photo" tag on selected filesystem objects. The AppleScript is written so you only need to make one change with each script and that is to change the TAG_NAME properties tag string. If a filesystem object already has a tag name on it, the script will add your tag name to that file or folder.


Here is the AppleScript that you copy/paste into Script Editor (Launchpad > Other > Script Editor). You then click the compile button, and save it twice: 1) as a text format tagname_photo.applescript in your preferred location, and then with option+Save As as a script format tagname_photo.scpt in /Users/yourname/Library/Scripts/Applications/Finder folder. The latter is where you will tell your new Voice Control command to find the workflow…


The AppleScript:


(*
AppleScript that checks selected filesystem obect(s) for existing tags
and adds the current tag name defined in the property beginning with TAG_

This script does not gather all defined tag names and attempt to validate
the user supplied tag name.

The user changes *one* location <== EDIT ==> for different tag name strings

Reference: https://discussions.apple.com/thread/252807460
Tested: macOS 11.4
VikingOSX, 2021-05-29, Apple Support Communities, No warranties expressed/implied
*)

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Cocoa"
use scripting additions

property NSUTF8StringEncoding : a reference to 4
property NSString : a reference to current application's NSString

property NSWorkspace : a reference to current application's NSWorkspace
property NSURL : a reference to current application's NSURL
property NSArray : a reference to current application's NSArray
property NSURLTagNamesKey : a reference to current application's NSURLTagNamesKey
property NSDictionary : a reference to current application's NSDictionary

property TAG_NAME : {"Photo"} # <== EDIT ==>

# assumption is that the filesystem object(s) are already selected before this
# script is invoked by Dictation.
set tagFileList to {}

# process selected items
tell application "Finder"
	if selection is {} then return
	set selList to selection
	repeat with anItem in selList
		copy POSIX path of (anItem as text) to the end of tagFileList
	end repeat
end tell

repeat with anItem in tagFileList
	my set_tag(anItem, TAG_NAME)
end repeat
return

on set_tag(theFile, atag)
	-- atag is always a list, even if single tag element
	-- place single, or multiple tags from atag on the specified file
	set existingTags to {}
	set tagArray to (NSArray's arrayWithArray:atag)'s mutableCopy()
	set existingTags to my file_tags(theFile)
	if (count of existingTags) ≥ 1 then
		# add the detected tag(s) to the existing TAG_NAME list item
		tagArray's addObjectsFromArray:existingTags
	end if
	
	set fileURL to NSURL's fileURLWithPath:theFile
	fileURL's setResourceValue:tagArray forKey:NSURLTagNamesKey |error|:(missing value)
	return
end set_tag

on file_tags(apath)
	-- Get all tags from the file, or an empty list if none
	-- apath = POSIX path to file
	set metadata to NSDictionary's dictionary()
	set aurl to NSURL's fileURLWithPath:apath
	set metadata to aurl's resourceValuesForKeys:{NSURLTagNamesKey} |error|:(missing value)
	-- file has no tags yet
	if (metadata's objectForKey:{NSURLTagNamesKey}) is missing value then return {""} as list
	-- file has tags, so return them as a list
	return (metadata's objectForKey:NSURLTagNamesKey) as list
end file_tags


In Accessibility > Voice Control > Commands… create your new command with the [+] button, and configure as follows. For testing purposes, I did not save the script as tagname_photo.scpt, but you should. And each variation of that script to match the voice command tag name should follow that format of the tag name in the filename.



Make certain that your file(s) are selected before speaking your voice command to trigger the script.

May 28, 2021 4:42 AM in response to danielardeer

When you speak "tag photo", and dictation recognizes the command, then it can do one of several things including triggering an AppleScript, or even an Automator workflow. That AppleScript has no means to obtain the spoken tag name from Dictation, and thus cannot set tag name "photo" or any other tag name on the selected file or folder. Unless your AppleScript was programmed with the tag name "photo" in it so it had that name to apply. This could get out of hand with several custom tag names.


Another solution might be the command "show tags". Dictation recognizes the command and fires an AppleScript that presents a scrollable list of your custom tag names, where you can select one or more tags to apply or remove on a selected file. That AppleScript code already exists in the first link you provided earlier.



May 27, 2021 5:06 PM in response to danielardeer

I took a closer look at this problem this afternoon, and it cannot be done. Not by me, anyway.


Speech recognition wants to match what you speak in a list of prefabricated strings ("add green", "remove red", etc) and does not perform speech-to-text capture. Thus, I cannot get the tag name string from your spoken command, or even the index into that list of commands, and that is crucial to manipulating tag names on filesystem objects.


Although Apple does have a Speech to text framework, it comes with an Apple privacy requirement that one must interactively request permission of the user to use their microphone and to send spoken content to Apple's speech recognition servers. I have never coded in this framework.


I will help you get the example code from the first link working as it pops a dialog allowing you to chose n-tuple tag names to apply on selected filesystem objects. Rather simple to use.



May 28, 2021 7:12 PM in response to danielardeer

Yes, the command recognition takes place with Dictation, and based on that recognition an AppleScript can be run. However, since AppleScript has no idea what tag name you want to be applied, that would require a separate AppleScript for each tag name that you use in your dictation command (e.g. tagname_photo.applescript, etc.). If that is what you want, I will write one of these for you, and the others are on you for your other commands and custom scripts.


This is the reason that I wrote that original script to get a list of all tag names and present it in a scrollable list, where one or more tag name selections would then be applied to selected files or folders. One script, not n-tuple scripts. It too, could be voice activated.

May 27, 2021 5:27 AM in response to danielardeer

The code that I provided in the first link still works (copy/paste) unchanged on macOS 11.4. However, there is additional code that needs to be added before the speech synthesizer can detect your spoken word, and compare that to a list of known tag names on your Mac.


I wrote an AppleScript several years ago that could detect spoken words and unhide a selected file extension. I will have to test if that code still works on Big Sur. Then I need to determine how to merge that code with some of the existing text tag manipulation code. The trick will be the word detection now, comparing the tag name to a list of current tag names, and applying it.


I will let you know if it is feasible or not, and a timeframe (if I have the time) to code it.


[Update: Just ran unchanged, the SpeechRecognitionServer AppleScript and it performed the spoken task. Now the real trick is merging the code, verifying your spoken tag to a list of valid tag names, and applying it to a selected filename.]

May 27, 2021 7:17 PM in response to VikingOSX

Thanks so much VikingOSX for your offer of support I really appreciate it!


Sorry I may not have been completely clear but I dont think need the script to actually recognise voice, as Apple's in built dictate option allows the voice command link to an Apple script, so all the AppleScript would need to do is perform the tagging (not recognise the voice)


so, if the Dictate command says "tag photo" for example, then that would link to the Apple Script to perform the action (to add the tag 'photo' to the file)


What do you think, is that doable? best, Dan

May 28, 2021 5:40 PM in response to VikingOSX

thanks VikingOSX, but if each is a different Command in Dictation, and the Dictation feature can recognise voice and run a particular script, that should work? eg if i say 'tag photo' then Dictation runs that particular script, wouldn't that work? (so the recognition is by Dictation not within the Applescript)? It does mean setting up a new script/Command for each rule, but that would be okay. thoughts? Dan

May 28, 2021 7:19 PM in response to VikingOSX

Hi VikingOSX, thank you perfect! Im trying to do a completely hands free option, so while the scrollable list is a great idea, I think option A is most hands-free therefore probably best option for me (even though will be a little bit of setting up with multiple scripts). Thank you so much for offering to help I appreciate this! Would be great to see this as an inbuild feature for Apple OS, as its a quick way to arrange/sort lots of screen shot files. Have a great day.

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

Applescript: Adding a custom tag to a selected file in Finder

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.