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?
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
Maybe this is managed by Spotlight (i.e. Metadata.framework) now? Since it’s Spotlight that actually stores the tags.—Jens
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.
I doubt it's Spotlight that stores them because they also work on vols where the Spotlight index is disabled.
--
Steve Mills
Drummer, Mac geek
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 []
}
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
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. 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 ZavatoneOn 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
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 ZavatoneOn 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
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
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
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
...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.
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.
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
/* @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
/* @class TiCloudTagReplicator */
-(void *)iCloudDictionary {
rdi = self->_store;
rax = [[rdi dictionaryRepresentation] objectForKey:@"FinderTagDict"];
return rax;
}
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.
sqlite3
now in Terminal, once I have a working code I'll post it here and update the SO question too.