I've added to 0xced's excellent answer so that the code can be packaged into a command-line tool that accepts the bundle ID as an argument. Forgive me if this is obvious to experienced Mac programmers, but as someone who has never used CoreFoundation I found this to be non-trivial.
#import <CoreFoundation/CoreFoundation.h>
extern CFDictionaryRef _CFPreferencesCopyApplicationMap(CFStringRef userName, CFStringRef hostName);
int main(int argc, char *argv[]) {
@autoreleasepool {
if (argc < 2) {
// Print usage string & exit.
fprintf(stderr, "usage: GetPrefDomains bundle_id\n");
exit(1);
}
// Get the bundle ID from the first command-line argument.
CFStringRef bundleID = CFStringCreateWithCString(NULL, argv[1], kCFStringEncodingUTF8);
// Get the list of preference domain urls.
CFDictionaryRef applicationMap = _CFPreferencesCopyApplicationMap(kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
CFArrayRef urls = CFDictionaryGetValue(applicationMap, bundleID);
// If no urls exist (invalid bundle ID), exit.
if (!urls) {
fprintf(stderr, "No preference domains found.\n");
exit(0);
}
// Print the paths to the preference domains.
CFIndex urlsCount = CFArrayGetCount(urls);
for (int i = 0; i < urlsCount; i++) {
CFURLRef url = CFArrayGetValueAtIndex(urls, i);
CFStringRef path = CFURLCopyPath(url);
printf("%s\n", CFStringGetCStringPtr(path, kCFStringEncodingUTF8));
}
// Clean up.
CFRelease(bundleID);
CFRelease(applicationMap);
}
}
Save the code as GetPrefDomains.m, compile, and invoke as:
GetPrefDomains com.apple.mail
This was useful to me because surprisingly the defaults
command is case-sensitive and misbehaves silently with certain Apple applications that are under the filesystem protections in SIP on Mojave 10.14 or later (Safari & Mail, most notably). Add in the fact that Apple's capitalization rules are not consistent (com.apple.mail
vs. com.apple.Notes
), sandboxed preference paths, and the fact that that the filesystem is not case-sensitive and you quickly run into some very frustrating edge cases.