Retrieve all available Finder tags on Monterey and later


Leo
 

I wonder if anyone has figured out a way to retrieve ALL available Finder tags on Monterey and later?

On pre-Monterey systems, it was possible by reading this file:

~/Library/SyncedPreferences/com.apple.finder.plist

However, this file doesn't exist anymore.

Other methods (such as reading Finder prefs or fileLabels of NSWorkspace) only return the 8 standard labels - but not any custom tags created by the user.

Googling the subject didn't produce any results.


Thanks for any info,
Leo 


 



On Jan 11, 2023, at 8:27 PM, Leo <var@...> wrote:

I wonder if anyone has figured out a way to retrieve ALL available Finder tags on Monterey and later? 

Maybe this is managed by Spotlight (i.e. Metadata.framework) now? Since it’s Spotlight that actually stores the tags.

—Jens


Gary L. Wade
 

I’m not sure if it’s officially documented somewhere, but what I’d do is add some tags to a particular file, see what that file looks like from the Terminal (e.g., xattr), and do a search for info about what it looks like vs another file that doesn’t have tags.  If there’s no official documentation once you see what you’re needing to see, file a feedback request to get it documented.

On Jan 11, 2023, at 8:27 PM, Leo <var@...> wrote:

I wonder if anyone has figured out a way to retrieve ALL available Finder tags on Monterey and later?

On pre-Monterey systems, it was possible by reading this file:

~/Library/SyncedPreferences/com.apple.finder.plist

However, this file doesn't exist anymore.

Other methods (such as reading Finder prefs or fileLabels of NSWorkspace) only return the 8 standard labels - but not any custom tags created by the user.

Googling the subject didn't produce any results.


Thanks for any info,
Leo 


Thomas Tempelmann
 

I doubt it's Spotlight that stores them because they also work on vols where the Spotlight index is disabled.

On Thu, Jan 12, 2023 at 7:01 PM Jens Alfke <jens@...> wrote:

Maybe this is managed by Spotlight (i.e. Metadata.framework) now? Since it’s Spotlight that actually stores the tags.

—Jens


Steve Mills
 

On Jan 12, 2023, at 12:37, Thomas Tempelmann <tempelmann@...> wrote:

I doubt it's Spotlight that stores them because they also work on vols where the Spotlight index is disabled.
Spotlight has to store them in order to find them, so they'd be stored there as well as where ever the file system puts them.

--
Steve Mills
Drummer, Mac geek


Alex Zavatone
 

There's unfortunately no API in macOS to retrieve the tags that you have created yourself in the Finder.

The solution is to parse the ~/Library/SyncedPreferences/com.apple.finder.plist:


This gets all Finder tags labels.

You can also select only the custom tags (ignore the system ones):

func customTagLabels() -> [String] {
    let url = URL(fileURLWithPath: "\(NSHomeDirectory())/Library/SyncedPreferences/com.apple.finder.plist")
    let keyPath = "values.FinderTagDict.value.FinderTags"
    if let d = try? Data(contentsOf: url) {
        if let plist = try? PropertyListSerialization.propertyList(from: d, options: [], format: nil),
            let pdict = plist as? NSDictionary,
            let ftags = pdict.value(forKeyPath: keyPath) as? [[AnyHashable: Any]]
        {
            return ftags.flatMap { tag in
                if let n = tag["n"] as? String,
                    tag.values.count != 2
                {
                    return n
                }
                return nil
            }
        }
    }
    return []
}

Text copied verbatum from StackOverflow.

Hope this helps.
Alex Zavatone

On Jan 13, 2023, at 8:31 AM, Steve Mills via groups.io <sjmills@...> wrote:

On Jan 12, 2023, at 12:37, Thomas Tempelmann <tempelmann@...> wrote:

I doubt it's Spotlight that stores them because they also work on vols where the Spotlight index is disabled.

Spotlight has to store them in order to find them, so they'd be stored there as well as where ever the file system puts them.

--
Steve Mills
Drummer, Mac geek








Alex Zavatone
 

A little more info.

Also, just as a FYI allTagLabels did return all tags, but customTagLabels didn't return all custom tags I had created. Going through the differences will actually probably be useful for me. 

On Monterey (12.0), this file is no longer present in that directory. It has moved to ~/Library/Preferences, BUT the contents are different, AND, they no longer contain all the necessary information. Now, only the tag names are present, but not the mapping to colors.

This looks like a shortcoming in the API.  I wonder if it’s it’s possible through AppleScript of all arcane solutions.  I’ll keep looking.

Alex Zavatone



On Jan 13, 2023, at 9:23 AM, Alex Zavatone via groups.io <zav@...> wrote:

There's unfortunately no API in macOS to retrieve the tags that you have created yourself in the Finder.

The solution is to parse the ~/Library/SyncedPreferences/com.apple.finder.plist:


This gets all Finder tags labels.

You can also select only the custom tags (ignore the system ones):

func customTagLabels() -> [String] {
    let url = URL(fileURLWithPath: "\(NSHomeDirectory())/Library/SyncedPreferences/com.apple.finder.plist")
    let keyPath = "values.FinderTagDict.value.FinderTags"
    if let d = try? Data(contentsOf: url) {
        if let plist = try? PropertyListSerialization.propertyList(from: d, options: [], format: nil),
            let pdict = plist as? NSDictionary,
            let ftags = pdict.value(forKeyPath: keyPath) as? [[AnyHashable: Any]]
        {
            return ftags.flatMap { tag in
                if let n = tag["n"] as? String,
                    tag.values.count != 2
                {
                    return n
                }
                return nil
            }
        }
    }
    return []
}

Text copied verbatum from StackOverflow.

Hope this helps.
Alex Zavatone

On Jan 13, 2023, at 8:31 AM, Steve Mills via groups.io <sjmills@...> wrote:

On Jan 12, 2023, at 12:37, Thomas Tempelmann <tempelmann@...> wrote:

I doubt it's Spotlight that stores them because they also work on vols where the Spotlight index is disabled.

Spotlight has to store them in order to find them, so they'd be stored there as well as where ever the file system puts them.

--
Steve Mills
Drummer, Mac geek









Alex Zavatone
 

A few options.

Create a unique tag and then use EasyFind to search all files on your drive to detect the one that contains that string.

Here’s a link to an AppleScript script that is supposed to return all tag names


(* Generate an inclusive list of standard and user defined tag names Tested: macOS 11.2.3 Author: VikingOSX, 2021-03-09, Apple Support Communities, no warranties *) use framework "AppKit" use scripting additions property NSWorkspace : a reference to current application's NSWorkspace set tagfile to POSIX path of ((path to home folder as text) & "Library:SyncedPreferences:com.apple.finder.plist") as text set keyPath to "values:FinderTagDict:value:FinderTags" set AWKCMD to " | awk '/n/ {print substr($0, index($0, $3))}'" -- if custom tag names were created in Finder this file will exist if exists ((POSIX file tagfile) as alias) = true then set allTags to paragraphs of (do shell script "/usr/libexec/PlistBuddy -c \"print " & keyPath & "\" " & tagfile's quoted form & AWKCMD) else -- no custom tag names exist, so get default Finder tag names set allTags to NSWorkspace's sharedWorkspace()'s fileLabels() as list end if if exists (allTags) is true then set {TID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, return} display dialog (items of allTags) as text with title "User Defined Tag Names" set AppleScript's text item delimiters to TID end if return


Hope that works on Monterey.
Cheers, 
Alex Zavatone



On Jan 13, 2023, at 9:23 AM, Alex Zavatone via groups.io <zav@...> wrote:

There's unfortunately no API in macOS to retrieve the tags that you have created yourself in the Finder.

The solution is to parse the ~/Library/SyncedPreferences/com.apple.finder.plist:


This gets all Finder tags labels.

You can also select only the custom tags (ignore the system ones):

func customTagLabels() -> [String] {
    let url = URL(fileURLWithPath: "\(NSHomeDirectory())/Library/SyncedPreferences/com.apple.finder.plist")
    let keyPath = "values.FinderTagDict.value.FinderTags"
    if let d = try? Data(contentsOf: url) {
        if let plist = try? PropertyListSerialization.propertyList(from: d, options: [], format: nil),
            let pdict = plist as? NSDictionary,
            let ftags = pdict.value(forKeyPath: keyPath) as? [[AnyHashable: Any]]
        {
            return ftags.flatMap { tag in
                if let n = tag["n"] as? String,
                    tag.values.count != 2
                {
                    return n
                }
                return nil
            }
        }
    }
    return []
}

Text copied verbatum from StackOverflow.

Hope this helps.
Alex Zavatone

On Jan 13, 2023, at 8:31 AM, Steve Mills via groups.io <sjmills@...> wrote:

On Jan 12, 2023, at 12:37, Thomas Tempelmann <tempelmann@...> wrote:

I doubt it's Spotlight that stores them because they also work on vols where the Spotlight index is disabled.

Spotlight has to store them in order to find them, so they'd be stored there as well as where ever the file system puts them.

--
Steve Mills
Drummer, Mac geek









Leo
 

Thanks Alex,
 
It's just all the solutions you mentioned are PRE-Monterey.
 
They all rely on the ~/Library/SyncedPreferences/com.apple.finder.plist file which doesn't exist since Monterey.
 
I myself was using this file for years.
 
At this point there doesn't seem to be a known way to retrieve the list of tags on Monterey and later.
 
So I was basically posting this question in hope that someone has figured out an unknown way.
 
 
Best,
Leo


Leo
 

On Thu, Jan 12, 2023 at 11:11 AM, Gary L. Wade wrote:
I’m not sure if it’s officially documented somewhere, but what I’d do is add some tags to a particular file, see what that file looks like from the Terminal (e.g., xattr), and do a search for info about what it looks like vs another file that doesn’t have tags.  If there’s no official documentation once you see what you’re needing to see, file a feedback request to get it documented.
 
Thanks Gary,

Yes, there's no issue to retrieve applied tags - xattr is indeed the simplest way to do this.

I'm talking about the list of all available tags - including the ones that are available to the user but not yet applied to any file.

I will file a feedback request to Apple eventually, which of course won't solve the issue for a few years at least.

Maybe I'll finally take advantage of those Technical Support Incident requests that Apple offers via the developer program.


Thanks,
Leo


Thomas Tempelmann
 

As the developer of FindAnyFile, which has a more powerful text search feature that EasyFind (it can find text in both UTF-8 and -16, in LE and BE, and even considers unicode pre/decomposition alternatives), I've already searched ALL files on a startup's data volume for the appearance of the name of a custom tag I added. No luck. Meaning it's no stored in a plist or something like that in plain text. Maybe in compressed form or in a database in a different format (again, compressed).

It must be stored _somewhere_, but I'm at the end of my wits, too.


On Fri, Jan 13, 2023 at 5:52 PM Leo <var@...> wrote:
On Thu, Jan 12, 2023 at 11:11 AM, Gary L. Wade wrote:
I’m not sure if it’s officially documented somewhere, but what I’d do is add some tags to a particular file, see what that file looks like from the Terminal (e.g., xattr), and do a search for info about what it looks like vs another file that doesn’t have tags.  If there’s no official documentation once you see what you’re needing to see, file a feedback request to get it documented.
 
Thanks Gary,

Yes, there's no issue to retrieve applied tags - xattr is indeed the simplest way to do this.

I'm talking about the list of all available tags - including the ones that are available to the user but not yet applied to any file.

I will file a feedback request to Apple eventually, which of course won't solve the issue for a few years at least.

Maybe I'll finally take advantage of those Technical Support Incident requests that Apple offers via the developer program.


Thanks,
Leo


Thomas Tempelmann
 

The best I could come up with so far is to use AppleScript to read the tag names from the Preferences window, see below.

But it sucks because it has to actually open the Finders's Prefs window.

use AppleScript version "2.4" -- Yosemite (10.10) or later

use scripting additions


set prefsWinWasOpen to false


tell application "Finder"

set prefs to Finder preferences

set prefsWin to window of prefs

tell prefsWin

try

get id

set prefsWinWasOpen to true

on error

set prefsWinWasOpen to false

open

end try

set current panel to Label Preferences panel

end tell

end tell


set rowNames to {}


tell application "System Events"

tell front window of (first application process whose name is "Finder")

set uiElems to entire contents

repeat with uiElem in uiElems

if class of uiElem is table then

set theTable to uiElem

exit repeat

end if

end repeat

set itsRows to rows of theTable

repeat with oneRow in itsRows

set end of rowNames to name of first UI element of oneRow

end repeat

end tell

end tell


if not prefsWinWasOpen then

tell application "Finder"

close prefsWin

end tell

end if


return rowNames



Leo
 

On Fri, Jan 13, 2023 at 09:25 AM, Thomas Tempelmann wrote:
...I've already searched ALL files on a startup's data volume for the appearance of the name of a custom tag I added. No luck. Meaning it's no stored in a plist or something like that in plain text. Maybe in compressed form or in a database in a different format (again, compressed).
Yep I did do a similar search and reached the same conclusion.


Leo
 

On Fri, Jan 13, 2023 at 10:35 AM, Thomas Tempelmann wrote:
The best I could come up with so far is to use AppleScript to read the tag names from the Preferences window, see below.
But it sucks because it has to actually open the Finders's Prefs window.
Thanks Thomas,

Interesting script. I'll keep it as a great example of UI scripting.

Like you mentioned, it has to open the actual Prefs window so not exactly suitable to, say, populate a popup with tags for the user to choose from. Plus the app I need it for is on Mac App Store where they don't allow System Events anyway.

I'm truly curious why Apple hides the list of tags so hard.


Leo



Thomas Tempelmann
 

The next step would be to use "Hopper Disassembler" and find the code that shows and sets up the Finder prefs window, in order to find out where it loads the information from. Hopper can turn the machine code into pseudo code and can also show the names of methods and strings, so it might lead to something.

Thomas


Thomas Tempelmann
 

Searching in Hopper for "tags" finds methods such as "readTagsFromCloud:". Do you have iCloud active? Maybe that's where they're now exclusively stored.

Could you check this: Create a second user where iCloud is not used. Does that then bring back the plist file that was used pre-Monterey?

And there's a class TTagInfoRegistry. It seems to manage the tags and observe changes to them.

The code inside readTagsFromCloud is below. Can anyone make sense of it? I'm not familiar with the Cloud APIs:

/* @class TiCloudTagReplicator */

-(void)readTagsFromCloud:(bool)arg2 {

    var_DC = arg2;

    r14 = [self iCloudDictionary];

    if (r14 != 0x0) {

            [r14 objectForKeyedSubscript:@"FinderTagDictVersion"];

            if (sub_1002b519c() == 0x2) {

                    [r14 objectForKeyedSubscript:@"FinderTagSerialNumber"];

                    r12 = sub_1002b519c();

                    if ((r12 > [TUserDefaults integerForRegID:0xb7]) || (var_DC != 0x0)) {

                            rbx = [r14 objectForKeyedSubscript:@"FinderTags"];

                            if (rbx != 0x0) {


Thomas


Thomas Tempelmann
 

This is probably also relevant when looking at the previous code:

/* @class TiCloudTagReplicator */

-(void *)iCloudDictionary {

    rdi = self->_store;

    rax = [[rdi dictionaryRepresentation] objectForKey:@"FinderTagDict"];

    return rax;

}


If I interpret this right, then the iCloud store for Finder has a FinderTagDict. I have no clue if other apps can access that, though.


Thomas Tempelmann
 

Oh, damnit! I looked at the High Sierra version of Finder. I only realized that now when I found the tags inside /Users/tempi/Library/SyncedPreferences/com.apple.finder.plist

Sigh. Will try again on Monterey now.


Thomas Tempelmann
 

Okay, found it now.

Searching with FAF for "FinderTagDictVersion" in ~/Library found it in ~/Library/SyncedPreferences/com.apple.kvs/com.apple.KeyValueService-Production.sqlite

And if you look into the ZSYSDMANAGEDKEYVALUE table, you'll find a single entry with ZKEY="FinderTagDict". The ZPLISTDATAVLUE contains a bplist record, which probably contains the tags with their names, as it's the same structure that we previously had inside com.apple.finder.plist.

I leave it to you to read that entry and read the binary plist into a dictionary in order to extract the data.

Oh, and out of courtesy to us all, please add an answer to the SO question once you've got working code: https://stackoverflow.com/q/41779969/43615

Good luck!


Leo
 

On Sat, Jan 14, 2023 at 04:17 AM, Thomas Tempelmann wrote:
Okay, found it now.
Oh wow. You're a genius. That's an impressive investigation. Thanks for getting to the bottom of it!

It'll take me some time to extract the data. I'm not new to databases - years of FileMaker coding - but not much experience with SQLite yet. 

I'm exploring sqlite3 now in Terminal, once I have a working code I'll post it here and update the SO question too.