Tags and labels with Mavericks

I know that labels have been converted by or replaced by tags and I’m curious if anyone has found a way to add or change them to existing or new files/folders. If possible, I’d like to add a specific color tag with the current month and another color with the current year, but haven’t been able to figure it out.

Thanks.

It can be done using an ASObjC-based Script Library. Save the following in a .scptd file in ~/Library/Script Libraries/:

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 ≠ 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:

When you have saved it, click on the Bundle Contents toolbar item in AppleScript Editor, click on the AppleScript/Objective-C Library button, and save.

Then to use it in a script, use something like this:

use theLib : script "<name of line here>"
use scripting additions

set theFile to (choose folder)
theLib's returnTagsFor:(POSIX path of theFile)
theLib's setTags:{"new", "improved"} forPath:(POSIX path of theFile)
theLib's addTags:{"best"} forPath:(POSIX path of theFile)

Hi Shane,
Thank you for your generous input. It’s taken me a couple of days to digest the concept and try to figure out how and why it works. I’m wondering what makes this method (ASObjC-based Script Library) work as opposed to just Applescript. I’m not anywhere familiar enough with Applescript to offer an alternative, I’m just wondering what an ASObjC-based Script Library offers that Applescript doesn’t.

I’m also not understanding the distinction between “SetTags” and “AddTags”. it seems pretty straight forward, but as far as I can tell they both replace existing tags or add them if nothing exists. I don’t really need to add to existing tags at the moment, but thinks it would be useful in the future. I’m also curious if there would be a way to change what used to be the label index or color of the tags.

An ASObjC-based Script Library is a way of calling the underlying Cocoa code via AppleScript. It’s a way of greatly increasing AppleScript’s abilities.

setTags will remove any existing tags, whereas addTags won’t.

This seems pretty self explanatory, but in playing around with it this morning the addTags seems to address the same tags each time changing that specific tag rather than appending it. In other words, if I had the tags “new” and “Important”, but ran the same script changing the “important” addTag to “relevant”, it would change “important” to “relevant” on the file. So, rather than having three tags, I still have two which seems rather counter-intuitive.

Maybe this short example may help.

use theLib : script "tags Lib"
use scripting additions

set theFile to (choose folder)
theLib's setTags:{"tag1", "tag2", "tag3"} forPath:(POSIX path of theFile)
set tags1 to theLib's returnTagsFor:(POSIX path of theFile)
log tags1 --> (*tag1, tag2, tag3*)
theLib's setTags:(rest of tags1) forPath:(POSIX path of theFile)
set tags2 to theLib's returnTagsFor:(POSIX path of theFile)
log tags2 --> (*tag2, tag3*)
theLib's addTags:{"tabouret"} forPath:(POSIX path of theFile)
set tags3 to theLib's returnTagsFor:(POSIX path of theFile)
log tags3 --> (*tag2, tag3, tabouret*)
theLib's setTags:{item -1 of tags3} forPath:(POSIX path of theFile)
set tags4 to theLib's returnTagsFor:(POSIX path of theFile)
log tags4 --> (*tabouret*)

Yvan KOENIG (VALLAURIS, France) jeudi 27 mars 2014 19:12:36

Do you not see the results as Yvan has posted?

I see it and think I have a vague understanding. Am I correct in assuming this is to assign a number of tags and that tabouret is the only one specified?

Also, I would like to assign a date tag to a newly duplicated file that would signify it’s creation/duplication date and keep getting and error -4960 which seems to refer to the “foundation” portion of the script when I try to apply it in this manner. Any idea what this would mean and how to remedy it?

I’m curious also as to whether the following shell script would be a more concise option and if it could be configured to do what I’d like:

do shell script "xattr -w com.apple.metadata:_kMDItemUserTags '(\"orange\\n6\",\"test\")' ~/desktop/Shell test file"

I’ve been trying to find a breakdown of what things like the “n6” refer to. Please bear with me, I’m not finding a lot consistent of information and am trying to get a handle on it.

Thanks in advance for any insight.

All the named tags were assigned by the script
tag1, tag2, tag3
then tag3 was removed
then tabouret was added
at last tag2 & tag3 were removed.

I thought that it was sufficiently clear.
The Event Log is :

tell application “AppleScript Editor”
choose folder
→ alias “Macintosh HD:Users:¢¢¢¢¢¢¢:Desktop:animaux:renards:”
end tell
(tag1, tag2, tag3)
(tag2, tag3)
(tag2, tag3, tabouret)
(tabouret)

Here (10.9.2 used in French) I didn’t got the error -4960.

Yvan KOENIG (VALLAURIS, France) jeudi 10 avril 2014 23:02:18

I have absolutely no doubt that you find clarity in this. I am merely trying to learn and have not as of yet found a source rudimentary enough for a simpleton such as myself to understand. I would imagine even someone as knowledgable as yourself began somewhere. I truly appreciate your taking the time to offer your input, but please understand this thread is pretty much all the information I have on this subject.

Yes – the command requires a list, and in that case the list has a single item.

Without seeing your code, I have no idea. I assume you’re converting the date to text. Is it too long?

I’m not sure what you mean by concise. It’s less code, but unless you’re putting it in a library, using it means more code. In any event, how concise code is is not often a good guide on what to do.

Hi Shane,
Again thank you for your reply I appreciate your taking the time to explain what I’m assuming is fairly rudimentary- I’ve been toying with this idea for about a week now and just today noticed it works as I wanted it to but only after running it once. In other words I get the -4960 error the first time I run it and then it works perfectly. I wish I knew why it triggers the error and then works, but I can definitely live with it knowing that.

I suspect you’ll find that error only happens in AppleScript Editor, first time after compile – it shouldn’t happen elsewhere. It’s a bug in AppleScript Editor.

I kind of hate to bring this up again, I seemed to annoy some people last time, but I’m still trying to learn. Please bear with me.

When I try to use above mentioned feature script in Yosemite, I get the error:

error “The variable |NSURL| is not defined.” number -2753 from “NSURL”

I’ve been looking for two days now - Is there something that has changed (Possibly the ASObjC portion since everything works up to this point) in Yosemite the makes this portion obsolete? It worked perfectly until switching.

Thank you.

No, nothing changed in Yosemite that would make it stop working.

Open the library script and make sure it says either NSURL or |NSURL|, and not |nsurl|.

I just changed it. It Was |NSURL|, changed it to NSURL. It seems I read somewhere it might make a difference.

Still got the error “The variable |NSURL| is not defined.” number -2753 from “NSURL”

This is the AppleScript/Objective-C Library portion. If I recall correctly, I just changed the name when I started using it.

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
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 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 ≠ 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:

That’s missing the most important line at the start:

use framework "Foundation"

Just added that and checked it, but still getting same error.

Could it have something to do with reinstalling my system? I installed a new drive about a month ago and wanted to do a clean install. A setting I might have changed?

No, there’s no setting involved. Go here:

www.macosxautomation.com/applescript/apps/Script_Libs.html

and download a new copy of FileTagsLib 1.0.0. Follow the instructions.

Wow. That’s perfect! Exactly what I was looking for - thank you.