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 !