I stumbled over these option this morning. I do not know when they were introduced, but I can see the options in 10.11 and 10.12. You can see them yourself with plutil -help
. (The options are not listed in the man
page.)
Note: Managing and editing Property List files and preferences is covered in much more detail and depth in my book “Property Lists, Preferences and Profiles for Apple Administrators“
Quick recap: plutil
manipulates property list files. Its main use up to now was to convert between property list formats (mainly from binary plists to something readable)
$ plutil -convert xml1 /path/to/propertylist.plist
and to check wether the syntax is valid
$plutil -lint /path/to/propertylist.plist
On Sierra, when you run plutil -help
you see some new options. These allow you to directly manipulate keys and values in a property list. This may be useful to replace PListBuddy
and defaults
to manipulate property lists.
When testing this I noticed one downside of plutil
immediately: it cannot be used to create a new property list file. Copy this to create an empty plist file:
<?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/>
</plist>
Inserting a new key/value pair
$ plutil -insert somekey -string somevalue test.plist
$ plutil -insert flag -bool YES test.plist
$ plutil -insert bestNumber -integer 1 test.plist
$ plutil -insert pi -float 3.141592 test.plist
This is pretty straightforward.
Inspecting a property list
You can use the -p
option to check our progress:
$ plutil -p test.plist
{
"newkey" => "newvalue"
"pi" => 3.141592
"bestNumber" => 1
"flag" => 1
}
This uses a non-standard output format, and the help text warns to use this parse plists. But it will do to look at the content.
Note: you can use plutil -p
to read the content of binary plists without converting!
Modifying values
You can modify values with the -replace
option.
$ plutil -replace flag -bool NO test.plist
Note that you can create new entries with -replace
:
$ plutil -replace otherkey -string othervalue test.plist
But you cannot overwrite an existing value with -insert
.
Deleting values
Very straightforward:
$ plutil -remove otherkey test.plist
Arrays
You can insert an empty:
$ plutil -insert list -xml '<array/>' test.plist
or
$ plutil -insert list -json '[]' test.plist
and add items to the array
$ plutil -insert list.0 -string 'list item 1' test.plist
$ plutil -insert list.1 -string 'list item 2' test.plist
$ plutil -insert list.2 -string 'list item 3' test.plist
or do it all at once
$ plutil -replace list -json '[ "yes", "no", "maybe" ]' test.plist
Dictionaries
$ plutil -insert dictionary -xml '<dict/>' test.plist
$ plutil -replace dictionary -json '{}' test.plist
$ plutil -insert dictionary.key1 -string value1 test.plist
$ plutil -replace dictionary -json '{ "otherkey" : "othervalue" }' test.plist
Getting Values
It looks like -extract
is meant to get values from a property list, but there is caveat. -extract
will not merely get the value of a key in the property list but will write it to a new file! And by default if you do not provide an new output file path with the -o
option it will overwrite the current file with the extracted data.
The proper, non-destructive syntax to use -extract
is:
$ plutil -extract list xml1 -o - test.plist
$ plutil -extract list json -o - test.plist
This will print a full property list file to stdout
. The -o -
option tells plutil
to print to stdout
. You can give a filename instead of the -
.
Since the output is encumbered with the json or xml syntax, it will be hard to use this to get to property list values in shell scripts. However, it still may be useful to, well, extract property list data from a complex plist file.
Conclusion
Keep in mind that there now is an alternative to defaults
and PlistBuddy
. Not having to convert a plist before changing data might be helpful, as well as the possibility to manipulate arrays and dictionaries with key paths. (You still should always use defaults
when working with preference plist files, since defaults
will go through the preferences system and possibility notify a process to update data.)
If you are using python or a similar high level scripting language it will still be more effective to use the libraries for property lists.
Did you come across anyway of working with deeply nested keys and values with plutil?
For example getting/setting the status in CLOUDDESKTOP:
defaults read MobileMeAccounts
{
Accounts = (
{
AccountAlternateDSID = “Blah”;
AccountDSID = 11111111;
AccountDescription = iCloud;
AccountID = “name@domain.com”;
AccountUUID = “Blah”;
DisplayName = “First Last”;
LoggedIn = 1;
Services = (
{
Name = CLOUDDESKTOP;
ServiceID = “com.apple.Dataclass.CloudDesktop”;
status = active;
},
{
Name = FAMILY;
ServiceID = “com.apple.Dataclass.Family”;
showManageFamily = 1;
},
plutil -extract Accounts.0.Services.0.status xml1 -o - ~/Library/Preferences/MobileMeAccounts.plist
or
/usr/libexec/PlistBuddy -c "Print :Accounts:0:Services:0:status" ~/Library/Preferences/MobileMeAccounts.plist
I think PlistBuddy is better in this case, since the output of plutil is a full xml plist in itself and harder to parse.
However, should the order of the items in either the Accounts array or the Services array change you will be messed up. Arrays should preserve order in property lists, but it might be that the process which writes these arrays may not care. You should at the very least verify that :Accounts:0:Services:0:Name is CLOUDDESKTOP before relying on the output of :Accounts:0:Services:0:status
For reliable results you should use a python script and CFPreferences. Or a Swift tool.