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 !