Adding Finder tags

ok, Finder tags are a cool thing. Nice replacement for comments, really.
The problem is, i like to use folder actions and want to automate this tagging process on files

Currently i know how to get tags:

#get tags from a file, folder
tell application "Finder" to set trg to item 1 of (get the selection)
set the_tags to paragraphs of (do shell script "mdls -raw -name kMDItemUserTags " & quoted form of POSIX path of (trg as text))

adding tags shouldnt be the big problem i think. Just some damn workaround with xattr. Couldnt find anything relevant.

Here are handlers to read, add and replace tags:

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

on returnTagsFor:posixPath -- get the tags
	set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
	set {theResult, theTags} to aURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
	if theTags = missing value then return {} -- because when there are none, it returns missing value
	return theTags as list
end returnTagsFor:

on setTags:tagList forPath:posixPath -- set the tags, replacing any existing
	set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
	aURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end setTags:forPath:

on addTags:tagList forPath:posixPath -- add to existing tags
	set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
	-- get existing tags
	set {theResult, theTags} to aURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
	if theTags is not missing value then -- add new tags
		set tagList to (theTags as list) & tagList
		set tagList to (current application's NSOrderedSet's orderedSetWithArray:tagList)'s allObjects() -- delete any duplicates
	end if
	aURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end addTags:forPath:

Till yesterday I used just returnTagsfor,
but today I needed to add tags. Both handlers adding or replacing tags donā€™t work. At least on 10.11

Iā€™m surprised to hear that. I canā€™t check under 10.11 here, however those handlers were all written on a system running 10.11. Are you passing a list of tags in both cases?

They all work on my own 10.11 system. But this siteā€™s software has been updated since Shane posted them, so of course the 'Ć¢ā€° ā€™ in the last handler has to be changed back to ā€˜ā‰ ā€™.

The second and third handlers both take two parameters: a list of strings denoting the tag colours and a POSIX path to the target item. On my system, the strings are in English. I donā€™t know what the situation is on systems localised for different languages. With setTags:forPath:, passing an empty tag list will remove all tags from the item.

Since all the handlers use ā€œinterleaved parameterā€ syntax, calls to them have be preceded by a reference to the script containing them (such as ā€˜myā€™ or ā€˜itsā€™).

My 10.11 system is comparatively slow, so it sometimes takes a few seconds for the tags to appear on screen. Adding a Finder ā€˜updateā€™ command seems to speed things up.

set theItem to (choose file)
my setTags:{"blue", "red"} forPath:(POSIX path of theItem)
tell application "Finder" to update theItem

One thing I have found is that tags set with these handlers can only be removed with them. The ā€œTagsā€¦ā€ item at the bottom of the Finderā€™s ā€œFileā€ menu doesnā€™t work to remove them.

One of the items in my list was a number variable for handler setTags:tagList. Itā€™s working now

Still, handler addTags:tagList refuses to work.

Edit.
addTags:tagList works now. And no, I neednā€™t to wait for the tags to appear:itā€™s instantaneous.
Thanks also Nigel!

This turns out to be because I was entering the tag names as lower-case strings: {ā€œblueā€, ā€œredā€}. These work in the scripts to set or delete tags with the required colours. But the Finderā€™s ā€œFileā€ menu sets tags with capitalised initial letters ā€” {ā€œBlueā€, ā€œRedā€} ā€” and itā€™s case sensitive when matching tags to remove. Shaneā€™s handlers appear to be case-insensitive, but itā€™s largely an effect of the way they work and the fact that the tag resource system produces appropriate tags for both, say, ā€œBlueā€ and ā€œblueā€. If both are set, you only see one blue tag on the screen, but there are two in the resource and Shaneā€™s returnTagsFor: handler will return both.

A standard format could be imposed by inserting this line at the tops of the setTags:forPath: and addTags:forPath handlers:

set tagList to (current application's NSArray's arrayWithArray:tagList)'s valueForKey:"capitalizedString"

Thanks ā€“ I didnā€™t notice that. Iā€™ve edited it now.

The tags donā€™t have to be colours ā€“ they can be any strings you like. The default ones are defined to be sort of backwards compatible with the old Finder labels. You can get those names like this:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"

current application's NSWorkspace's sharedWorkspace()'s fileLabels() as list

Just be aware that it also strips custom icons in 10.13.

Hello! I want to add some tags using an Automator Quick Action

When calling addTags Iā€™m getting a Syntax Error: Expected end of line, etc. but found ā€œ:ā€.

set filePath to "/Users/myname/Desktop/1.zip"
set tagToAdd to "Orange"
addTags:{tagToAdd} forPath:filePath

(Sorry, very new to AppleScript)

Jeez AppleScript is so stange :sweat_smile: thanks a lot @Fredrik71 !