plutil(1) does: (which, honestly, isn't much)./usr/libexec/PlistBuddy: because it's only friendly to MacOS users, and even that, barely.plutil(1)'s -p switch, but more readily machine readable and grep(1)-friendly.plutil(1) and the code in CFBinaryPlist.c require JCOLOR=1 as with the rest of my tools. And export/setenv to apply as default. Note when piping, you'll need less -R, rather than more. Colors will identify the datatypes.morpheus@Zephyr (~/Documents/Work/SimPLISTic) %JCOLOR=1 ./jlutil /System/Library/LaunchDaemons/com.apple.syslogd.plist 14:46 HopefullyExitsLast: true JetsamProperties: JetsamPriority: -49 JetsamMemoryLimit: 300 EnvironmentVariables: ASL_DISABLE: 1 POSIXSpawnType: Adaptive MachServices: com.apple.system.logger: ResetAtClose: true EnableTransactions: true ProgramArguments[0]: /usr/sbin/syslogd Sockets: BSDSystemLogger: SockPathMode: 438 SockPathName: /var/run/syslog SockType: dgram OnDemand: false Label: com.apple.syslogd
jlutil so it gets all UTF-8,UTF-16 and UTF-32 correctly, so as to support any language (important, since plists often i18n-alize) and not (perish the thought...) leave any emoji behind...
morpheus@Zephyr (~/Documents/Work/SimPLISTic) %./jlutil -x tests/com.apple.time-zh-CN.plist 14:45
<?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">
<dict>
<key>VSRecognitionClasses</key>
<array>
<dict>
<key>VSRecognitionClassIdentifier</key>
<string>command</string>
<key>VSRecognitionClassElements</key>
<array>
<string>几点了</string>
<string>什么时间</string>
<string>现在是几点钟</string>
<string>现在的时间是</string>
</array>
<key>VSRecognitionClassType</key>
<string>VSRecognitionClassTypeCommand</string>
</dict>
</array>
<key>VSRecognitionSequences</key>
<array>
<dict>
<key>VSRecognitionSequenceElements</key>
<array>
<string>command</string>
</array>
</dict>
</array>
</dict>
</plist>
root@Zephyr (~/Documents/Work/SimPLISTic) #hexdump -C /tmp/out2.bplist16
00000000 62 70 6c 69 73 74 31 36 a0 d6 00 00 00 00 00 00 |bplist16........|
00000010 00 7f 11 6d 64 6f 4d 61 72 6b 55 73 65 72 41 63 |...mdoMarkUserAc|
00000020 74 69 76 69 74 79 41 73 44 69 72 74 79 3a 66 6f |tivityAsDirty:fo|
00000030 72 63 65 49 6d 6d 65 64 69 61 74 65 3a 77 65 62 |rceImmediate:web|
00000040 70 61 67 65 55 52 4c 3a 65 78 70 69 72 61 74 69 |pageURL:expirati|
00000050 6f 6e 3a 68 61 73 69 43 6c 6f 75 64 44 6f 63 75 |on:hasiCloudDocu|
00000060 6d 65 6e 74 3a 68 61 73 55 6e 73 79 6e 63 68 72 |ment:hasUnsynchr|
00000070 6f 6e 69 7a 65 64 69 43 6c 6f 75 64 44 6f 63 3a |onizediCloudDoc:|
00000080 00 7a 76 40 3a 40 63 40 40 63 63 00 a0 d6 00 00 |.zv@:@c@@cc.....|
00000090 00 00 00 00 00 d0 ce 00 00 00 00 00 00 00 77 24 |..............w$|
000000a0 63 6c 61 73 73 00 77 4e 53 55 55 49 44 00 7d 4e |class.wNSUUID.}N|
000000b0 53 2e 75 75 69 64 62 79 74 65 73 00 4f 11 10 b8 |S.uuidbytes.O...|
000000c0 fc 22 8b e6 86 4e 6d 99 9f 3a c1 31 61 58 0a 11 |."...Nm..:.1aX..|
000000d0 01 e0 e0 11 00 11 00 |.......|
000000d7
root@Zephyr (~/Documents/Work/SimPLISTic) #jlutil !$
jlutil /tmp/out2.bplist16
0: doMarkUserActivityAsDirty:forceImmediate:webpageURL:expiration:hasiCloudDocument:hasUnsynchronizediCloudDoc:
1: v@:@c@@cc
2:
0:
$class: NSUUID
NS.uuidbytes: data
1: 1
2: NULL
3: NULL
4: 0
5: 0
This makes it easy to piece together remote invocations of ObjC over NSXPC: In the example above, the selector is doMarkUserActivityAsDirty:forceImmediate:webpageURL:expiration:hasiCloudDocument:hasUnsynchronizediCloudDoc:
with an Objective-C protocol of v@:@c@@cc (return void, get id, char, id, id char char) with the object (an NSUUID, the activity), a '1' for the 2nd argument
(counting from 0) two NULLs for webPageURL and expiration, a false for hasiCloudDocument and another false for hasUnsynchronizediCloudDoc.
You can get bplist16 output from breakpointing XPC in lldb and mem read -o .. or using XPoCe 2.5.
plutil(1)? - Because they're displayed in order of appearance (from the top object downwards), and not their order in memory. When loaded into a CFDict and then enumerated (the way plutil(1) does it) the elements get sorted.