Let’s address the headline first. This post is about the tags on files that Apple started supporting in Mavericks. Up until iOS 11, they didn’t work on iOS devices, so they eventually became “Finder tags.” I think “Apple Tags” is going to have to be the nomenclature moving forward (now that they’re starting to work on iOS as well), but I don’t think it’s a widely accepted phrase yet. So I’ll use “Finder tags” for a little while longer.
I have a handful of scripts for manipulating tags from the command line, including the most complete (and useful to me) one, vitag. There’s an excellent CLI from James Berry called “tag” that I use frequently, but I sometimes implement more “down and dirty” techniques in scripts.1 If you’re just looking for a ready-to-go tool, grab tag and skip the rest of this.
Last weekend I wrote a script to handle cleaning up my system’s tags, merging synonymous tags, fixing spacing and punctuation, making casing and pluralization consistent, and various other nitpicks that have gotten messy in my taxonomy over time. It used the same basic Ruby classes that I used in vitag, which you can reference on GitHub for a more full-fledged version of these tips. I’m not ready to publish this last script yet, but I thought I’d point out a few simple tricks for those working on their own solutions.
Reading tags on a file
Tags are stored in extended attributes on the files, in a metadata attribute with the key
Trying to view them using the
xattr tool almost always results in a hex dump, and converting it results in a binary plist, and converting that gives you messy results.
I’ve found it better to just get the raw output from
I can parse that response, split lines, remove commas, etc., and turn it into an array of tags I can work with.
Writing tags to a file
Tags are written to files using
xattr. They need to be passed to
xattr in Plist format (XML) with an array of string elements containing the tags.
When you write tags to the file using
xattr, it will obliterate any existing tags, so note that if you want to add tags instead of replacing them, you need to read the tags into an array as shown above, modify and update the array, then write the whole thing back to the file.
The command for doing this is:
xattr -w com.apple.metadata:_kMDItemUserTags '[plist data]' [file]
The xml string you need looks like this (line breaks for display, easiest to pass as one long string:
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <array> <string>tag1</string> <string>tag2</string> </array> </plist>
So the command for writing “tag1” and “tag2” to /file/path would be:
xattr -w com.apple.metadata:_kMDItemUserTags '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><array><string>tag1</string><string>tag2</string></array></plist>' /file/path
Here’s a Ruby snippet showing the building of the XML string and shelling out to write it to the file:
The colors associated with tags like “Blue” and “Orange” (default label names) are stored in a different attribute (
com.apple.FinderInfo). This dates back a ways, and there’s really no point in directly writing to this attribute anymore. It’s easiest just to change the tags. Remove “Blue” and add “Orange.”
Writing a color to a file, e.g.:
xattr -wx com.apple.FinderInfo "0000000000000000000900000000000000000000000000000000000000000000" filename
…will simply apply the Blue tag to the file automatically. So just apply the Blue tag and skip the hex strings.
Often just for the sake of not having any external dependencies…↩