Getting/Setting Mavericks Tags

It’s great that Apple has provided a means for us to associate files and folders with their new “tags” implementation.

However, after digging around, I don’t see that they have made any attempt to enable access to them via AppleScript.

Is there a way using ASOC perhaps?

Yes, there is. What are you wanting to do?

I want to apply tags to folders that are part of a hierarchy, then, using folder actions, when a file is copied to a folder, the script would traverse up the hierarchy, appending the tags of each folder and then assigning those tags to the file which originated the action.

Think:

Company - tag=ACME
Division - tag=ACME Boots
Brand - tag=Justin
Product - tag=Buttkickers

Placing a photo of the fall collection of Buttkicker Boots in the Product folder would automatically assign the tags:
ACME, ACME Boots, Justin, Buttkickers

Later, I can use the tags to assign keywords or metadata fields in a Digital Asset Management system.

This would just give me a simple, tactical method for providing my clients with a “tag-by-sorting” workflow.

I have already written a proof-of-concept that traverses and accumulates Finder Label Index integers which are then copied into the Finder Comment of the triggering file.

This should cover what you want:

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:

So:

use theLib : script "<path to lib>"
use scripting additions

set theFile to (choose file)
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)

I SEEM to be almost there.

Since this is my first Library Script, I created a folder “Script Libraries” in the boot volumes primary “Library” folder.

I placed a compiled version of your first example script within, naming it “finderTagLib.scpt”

However, when I try to access it using the second provided example, I get the error:

Can’t get framework “Foundation” of «script “finderTagLib”». Access not allowed.

Ideas?

Close. You need to save it as a .scptd, not .scpt. Then when you have saved it, the Bundle Contents tool at the top of the script’s window becomes enabled; click on it, and in the drawer that appears, click on the checkbox AppleScript/Objective-C Library. Save again.

Fantastic!

You set me on the right path, as well as got me started with an understanding of the implementation of Script Libraries.

Works Great!

FYI, you can read more about libraries here: macscripter.net/viewtopic.php?pid=168712#p168712

Hi,

thanks for the help! I can now programmatically change tags of files using the supplied scripts. I want to use these templates in combination with Hazel, calling a script to add tags to a file. I can’t use the ordinary tag functions of Hazel since I don’t know what tags i need before running Hazel. Tags also depend on previous actions on the file and data found during Hazel processing.

In using the templates, it seems I need to call an external script in Hazel starting with
on hazelProcessFile(theFile)
– my code
end hazelProcessFile(theFile)

I need to supply the references:
use theLib : script “finderTagLib”
use scripting additions
in order to be able to tag files.

If I supply the references before the definition of the handler, I can compile and run the script. The tagging doesn’t seem to work, though.

If I supply the references directly after the definition of the handler, I get a syntax error upon compilation of the script, stating suspected “end” but found “use” (in a direct translation from swedish). What am I doing wrong here?

Best regards,
Björn

I suspect you’re hitting a bug in Mavericks. If Hazel is resetting the target of the script, it would explain what you are seeing. The bug is listed as fixed in Yosemite.

Thanks for the prompt reply.

OK, since I’m not that used to handlers, I’ve gotten it correct that the “referencing” should be used outside of the handler?

I thought that the references wouldn’t be used if they were stated outside of the handler … But then again, I guess the script would return some sort of error once the call to the library was made…

So, for future reference, I should “reference”/“call” my libraries outside of the handler?

Regards,
Björn

Any use statements should be at the beginning of your script. When you say:

use theLib : script "finderTagLib"

you are defining a property called theLib, and storing a reference to the script library in it. You can’t define properties at other than the top level of a script object.

But you don’t need to do it this way. You can use a tell statement instead:

tell script "finderTagLib"
 -- call lib's handlers here
end tell

Thanks Stanley,

seems to work correct under Yosemite, but could also be due to my poor scripting skills that it couldn’t work out in Mavericks.

Regards,
Björn

That sounds like you hadn’t checked the AppleScript/Objective-C checkbox, which isn’t required in Yosemite. For that matter, you can run the code directly in Yosemite, without the need for a library.

Hi Stanley.

Actually, that wasn’t the problem. I had tried using the bundle using another script which worked out fine.

Anyways, seems to work out fine just now.

All the best,
Björn