Ok so I ended up going the command-line way using “xattr”. It allows to display or change file extended attributes. Labels are one of the extended attributes.
I can’t describe all parts in details, but I’ll try to explain what I can.as once everything worked, I have not documented what each component does. But in short,
Reading the labels:
xattr -p com.apple.metadata:_kMDItemUserTags /path/to/file | xxd -r -p | plutil -convert json - -o -
In more details:
xattr -p com.apple.metadata:_kMDItemUserTags /path/to/file
xattr allows to read and manipulate extended attributes. Labels are one of them. It outputs the result as a hex dump.
- -p : Print the value associated with the attribute name
- com.apple.metadata:_kMDItemUserTags is the attribute that stores the labels
- /path/to/file : valid shell path (properly escaped)
xxd -r -p
xxd is a convert utility from hex dump to binary data
- -r : reverse convert (from hex dump to binary)
- -p : output as plain text
plutil -convert json - -o -
plutil is a utility to work with property lists and will perform the final conversion in json so it’s easier to work with.
- -convert json : convert the property list to json
-
- : take standard in as input
- -o : allows to specify a path for output (in our case, will be redirected)
-
- : output is redirected to standard out, which will end up in the result property of the Xojo shell.
The final output is a string in json format which looks like:
["Yellow\
5","Red\
6","Work"]
Each item contains the label name followed by the color code (if there’s a color). The name and color are separated by the "
" string. The color codes are: 0=none | 1=gray | 2=green | 3=purple | 4=blue | 5=yellow | 6=red
Writing labels
To set the tags, rebuild the string in the same format. The same utilities are used in reverse order with some different options, but you can basically figure out the process. Any new label will still be assigned and shown, but not available in the label popup list in the finder.
xattr -xw com.apple.metadata:_kMDItemUserTags $(echo '[labelname1,labelname2,labelname3]' | plutil -convert binary1 - -o - | xxd -p -c 256 -u) /path/to/file
My needs were to replicate the labels from one file to another. I have an audio converter application and I needed the converted files to have the same labels as the originals. So I have created a small class that reads the labels, and then sets them on another file. It does not allow to manually define the labels, but it would be trivial to add.
Here’s some sample code (adapted from my class but not tested)
[code]Private Sub ReadLabels(targetFile as FolderItem)
// READ FILE LABELS
dim theLabels() as string
dim theColors() as integer
if targetFile <> nil and targetFile.Exists = true then
dim s as new shell
s.Execute “xattr -p com.apple.metadata:_kMDItemUserTags " + targetFile.ShellPath + " | xxd -r -p | plutil -convert json - -o -”
if s.ErrorCode = 0 then
dim rawResult as string = s.Result
dim jsonLabels as new JSONItem(rawResult)
dim lastItem as integer
lastItem = jsonLabels.Count - 1
for i as integer = 0 to lastItem
dim item as string
item = jsonLabels.Value(i).StringValue
dim parts() as string
parts = item.Split(&u0A)
theLabels.Append parts(0)
if parts.Ubound > 0 then
theColors.Append(parts(1).val)
else
theColors.Append(0)
end if
next
end if
end if
// do your stuff with the labels and the color codes
// theLabels contains an array of label names
// theColors contains the matching color codes
End Sub[/code]
To write the labels for a given file, create a properly formatted string as: [“hot
1”,“projectX”,“mytag1”]
Private Sub SetLabels(targetFile as FolderItem,jsonlist as string)
// WRITE FILE LABELS
dim cmd as string = "xattr -xw com.apple.metadata:_kMDItemUserTags $(echo '" + _
jsonlist + "' | plutil -convert binary1 - -o - | xxd -p -c 256 -u) " + _
targetFile.ShellPath
dim s as new Shell
s.Execute cmd
End Sub
In terminal, use “man” if you want to learn more about the different tools used:
man xattr
man xxd
man plutil