13

Is it possible to tag a file or folder in mavericks via terminal command?

4
  • 1
    Yes it is. The tags are stored / read using xattr and stored in com.apple.metadata:_kMDItemUserTags. Do you want to edit in a more specific question (perhaps use python to easily set a tag named "foo" to a specific file) or are you just curious if it's technically possible?
    – bmike
    Commented Nov 15, 2013 at 15:23
  • related question here
    – Asmus
    Commented Nov 15, 2013 at 16:55
  • 1
    @bmike thanks, yeah I want to edit programmatically :P Commented Nov 18, 2013 at 8:55
  • In Stack Overflow, with an answer from me: How can I add OS X “tags” to files programmatically? (2013-11-01) Commented Jul 26, 2015 at 7:51

2 Answers 2

27

You can use xattr. This copies the tags from file1 to file2:

xattr -wx com.apple.metadata:_kMDItemUserTags "$(xattr -px com.apple.metadata:_kMDItemUserTags file1)" file2;xattr -wx com.apple.FinderInfo "$(xattr -px com.apple.FinderInfo file1)" file2

The tags are stored in a property list as a single array of strings:

$ xattr -p com.apple.metadata:_kMDItemUserTags file3|xxd -r -p|plutil -convert xml1 - -o -
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <string>Red
6</string>
    <string>new tag</string>
    <string>Orange
7</string>
    <string>Yellow
5</string>
    <string>Green
2</string>
    <string>Blue
4</string>
    <string>Purple
3</string>
    <string>Gray
1</string>
</array>
</plist>

If the kColor flag in com.apple.FinderInfo is unset, Finder doesn't show the circles for colors. If the kColor flag is set to orange and the file has the red tag, Finder shows both red and orange circles. You can set the kColor flag with AppleScript:

xattr -w com.apple.metadata:_kMDItemUserTags '("Red\n6","new tag")' ~/desktop/file4;osascript -e 'on run {a}' -e 'tell app "Finder" to set label index of (POSIX file a as alias) to item 1 of {2, 1, 3, 6, 4, 5, 7}' -e end ~/desktop/file4

xattr -p com.apple.FinderInfo file|head -n1|cut -c28-29 prints the value of the bits used for the kColor flag. Red is C, orange is E, yellow is A, green is 4, blue is 8, magenta is 6, and gray is 2. The flag that would add 1 to the values is not used in OS X.

Edit: you can also use tag:

tag -l file # list
tag -a tag1 file # add
tag -s red,blue file # set
tag -r \* file # remove all tags
tag -f green # find all files with the green tag
tag -f \* # find all files with tags
tag -m red * # match (print files in * that have the red tag)

tag can be installed with brew install tag or sudo port install tag.

$ tag -h
tag - A tool for manipulating and querying file tags.
  usage:
    tag -a | --add <tags> <file>...     Add tags to file
    tag -r | --remove <tags> <file>...  Remove tags from file
    tag -s | --set <tags> <file>...     Set tags on file
    tag -m | --match <tags> <file>...   Display files with matching tags
    tag -l | --list <file>...           List the tags on file
    tag -f | --find <tags>              Find all files with tags
  <tags> is a comma-separated list of tag names; use * to match/find any tag.
  additional options:
        -v | --version      Display version
        -h | --help         Display this help
        -n | --name         Turn on filename display in output (default)
        -N | --no-name      Turn off filename display in output (list)
        -t | --tags         Turn on tags display in output (find, match)
        -T | --no-tags      Turn off tags display in output (list)
        -g | --garrulous    Display tags each on own line (list, find, match)
        -G | --no-garrulous Display tags comma-separated after filename (default)
        -H | --home         Find tagged files only in user home directory
        -L | --local        Find tagged files only in home + local filesystems (default)
        -R | --network      Find tagged files in home + local + network filesystems
        -0 | --nul          Terminate lines with NUL (\0) for use with xargs -0
6

It's possible to manipulate tags via pure bash commands. There's no need for a 3rd party "tag" util.

This command lists all tags of a file ($src):

xattr -px com.apple.metadata:_kMDItemUserTags "$src" | \
    xxd -r -p - - | plutil -convert json -o - - | sed 's/[][]//g' | tr ',' '\n'

And here is how you can add a tag ($newtag) to a file ($src):

xattr -wx com.apple.metadata:_kMDItemUserTags \
    "$(xattr -px com.apple.metadata:_kMDItemUserTags "$src" | \
    xxd -r -p - - | plutil -convert json -o - - | sed 's/[][]//g' | tr ',' '\n' | \
    (cat -; echo \"$newtag\") | sort -u | grep . | tr '\n' ',' | sed 's/,$//' | \
    sed 's/\(.*\)/[\1]/' | plutil -convert binary1 -o - - | xxd -p - -)" "$src"

Here is a small shell script which exports a "tags" function. Usage:

tags <file>
Lists all tags of a file

tags -add <tag> <file>
Adds tag to a file

The function could be easily extend to support removing as well.

tags() {
    # tags system explained: http://arstechnica.com/apple/2013/10/os-x-10-9/9/
    local src=$1
    local action="get"

    if [[ $src == "-add" ]]; then
        src=$3
        local newtag=$2
        local action="add"
    fi

    # hex -> bin -> json -> lines
    local hexToLines="xxd -r -p - - | plutil -convert json -o - - | sed 's/[][]//g' | tr ',' '\n'"

    # lines -> json -> bin -> hex
    local linesToHex="tr '\n' ',' | echo [\$(sed 's/,$//')] | plutil -convert binary1 -o - - | xxd -p - -"

    local gettags="xattr -px com.apple.metadata:_kMDItemUserTags \"$src\" 2> /dev/null | $hexToLines | sed 's/.*Property List error.*//'"

    if [[ $action == "get" ]]; then
        sh -c "$gettags"
    else
        local add="(cat -; echo \\\"$newtag\\\") | sort -u"
        local write="xattr -wx com.apple.metadata:_kMDItemUserTags \"\$($gettags | $add | grep . | $linesToHex)\" \"$src\""

        sh -c "$write"
    fi
}
export -f tags
4
  • Yikes, those are long lines! I suggested a wrapping edit. I think they might be better done as small shell scripts, though.
    – Mattie
    Commented Jan 31, 2014 at 2:21
  • Your xattr -wx command fails when the file doesn't already have any tags on it. How can I avoid this? Commented Oct 10, 2015 at 17:43
  • Seems to have some issue in the latest OS X (El Cap 10.11.4). Running the xattr -px … command you've given to show the tags on one of my folders gives the following output: "language:Objective-C\n2" (newline) "platform:iOS\n4". Honestly, if you're going to wrap up your moderately-complex shell code into a bash function, you're sort of just duplicating the effort of tag, which has the advantage of being community well-maintained. Commented May 11, 2016 at 19:18
  • @SlippD.Thompson, how is wrapping up shell code into a bash function anything to do with "effort duplication" of a to-be compiled tool?... You don't have to give a pro-con analysis for this and 'tag', you choose whatever you like. The statement of this solution is that you don't need a 3rd party tool to achieve the desired functionality.
    – sarimarton
    Commented Jul 3, 2018 at 8:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .