You can make a difference in the Apple Support Community!

When you sign up with your Apple Account, you can provide valuable feedback to other community members by upvoting helpful replies and User Tips.

Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

How to get a value from a plist file using the defaults command?

I have this 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>
          <key>Dictionary1</key>
          <dict>
                    <key>Dictionary2</key>
                    <dict>
                              <key>Dictionary3-auto</key>
                              <dict>
                                        <key>Number1</key>
                                        <integer>1</integer>
                              </dict>
                    </dict>
          </dict>
</dict>
</plist>


User uploaded file

and I wonder how I can get a value for the Number1 key using Terminal. How should the "defaults read" command look like?

OS X Mavericks (10.9.2)

Posted on May 6, 2014 5:48 AM

Reply
Question marked as Top-ranking reply

Posted on May 6, 2014 5:56 AM

Hello


I don't think defaults(1) is the right tool for such retrieval. You may use /usr/libexec/PlistBuddy instead.


#!/bin/bash

/usr/libexec/PlistBuddy -c 'Print :Dictionary1:Dictionary2:Dictionary3-auto:Number1' ~/desktop/a.plist


Regards,

H

5 replies
Sort By: 
Question marked as Top-ranking reply

May 6, 2014 5:56 AM in response to Falafoni

Hello


I don't think defaults(1) is the right tool for such retrieval. You may use /usr/libexec/PlistBuddy instead.


#!/bin/bash

/usr/libexec/PlistBuddy -c 'Print :Dictionary1:Dictionary2:Dictionary3-auto:Number1' ~/desktop/a.plist


Regards,

H

Reply

May 7, 2014 4:45 AM in response to MrHoffman

Hello


If PlistBuddy is not up to date to support recent preferences caching, here's a rubycocoa script using defaults(1) for reading plist and retrieve value at given key path. Key path is in the form as used in PlistBuddy except for using / instead of :.


E.g.,


./plist_read.rb '/Dictionary1/Dictionary2/Dictionary3-auto/Array1/0/String1' a.plist



# plist_read.rb


#!/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby -w
require 'osx/cocoa'
include OSX

def dict_get_value_at_path(dict, keypath)
    v, p = dict, ''
    keypath.split('/').select {|a| a.length > 0}.each do |k|
        p << '/' + k
        if v.className == 'NSCFDictionary' && v.key?(k)
            v = v[k]
        elsif v.className == 'NSCFArray' && k =~ /^\d+$/ && v[k.to_i]
            v = v[k.to_i]
        else
            $stderr.puts '%s: No such key path.' % p
            return nil
        end
    end
    return v
end

raise ArgumentError, %Q[Usage: #{File.basename($0)} keypath plist] unless ARGV.length == 2
keypath, infile = ARGV

s = %x[defaults read "#{File.expand_path(infile).chomp('.plist')}"]
exit $? >> 8 if s == ''

plist = s.to_ns.propertyList
exit 1 unless plist

value = dict_get_value_at_path(plist, keypath)
exit 2 unless value
puts value



# test.sh (plist_read.rb is assumed to be saved in ~/desktop)


#!/bin/bash

cd ~/desktop

cat <<'EOF' > org.my.domain.plist
<?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>Dictionary1</key>
    <dict>
        <key>Dictionary2</key>
        <dict>
            <key>Dictionary3-auto</key>
            <dict>
                <key>Number1</key>
                <integer>1</integer>
                <key>Boolean1</key>
                <true/>
                <key>Array1</key>
                <array>
                    <dict>
                        <key>String1</key>
                        <string>abc</string>
                    </dict>
                    <dict>
                        <key>String1</key>
                        <string>def</string>
                    </dict>
                </array>
            </dict>
        </dict>
    </dict>
</dict>
</plist>
EOF

./plist_read.rb '/Dictionary1/Dictionary2/Dictionary3-auto/Array1/0/String1' org.my.domain.plist



Just in case this might be of some use.

All the best,

H



PS. Here's another version of plist_read.rb using CFPreferencesAppSynchronize() which is not well-tested, for I'm using 10.6.8.


#!/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby -w
require 'osx/cocoa'
include OSX

def dict_get_value_at_path(dict, keypath)
    v, p = dict, ''
    keypath.split('/').select {|a| a.length > 0}.each do |k|
        p << '/' + k
        if v.className == 'NSCFDictionary' && v.key?(k)
            v = v[k]
        elsif v.className == 'NSCFArray' && k =~ /^\d+$/ && v[k.to_i]
            v = v[k.to_i]
        else
            $stderr.puts '%s: No such key path.' % p
            return nil
        end
    end
    return v
end

raise ArgumentError, %Q[Usage: #{File.basename($0)} keypath plist] unless ARGV.length == 2
keypath, infile = ARGV

bundleid = File.basename(infile, '.plist')
b = CFPreferencesAppSynchronize(bundleid)
$stderr.puts 'CFPreferencesAppSynchronize() failed for %s' % bundleid unless b

plist = NSDictionary.dictionaryWithContentsOfFile(infile)
unless plist
    $stderr.puts '%s: Failed to get dictionary.' % infile
    exit 1
end

value = dict_get_value_at_path(plist, keypath)
exit 2 unless value
puts value
Reply

May 6, 2014 7:08 AM in response to Hiroto

I'd approach PlistBuddy with some caution. The only mechanism that's compatible with the preferences caching present in Mountain Lion 10.8 and Mavericks 10.9 is the defaults command or the CFPreferences methods, and not AFAIK PlistBuddy or the older Xcode stuff — this situation does seem rather crazy, and hopefully will (did?) get fixed. (If you're just tossing data around via a plist and not changing and not caching it within an app, ignore this...)

#!/bin/bash

unset FOO

printf "Before: %s\n" $FOO

bar="MyValueToSave"

defaults write ~/Desktop/MyScriptPrefs MyKey $bar

export FOO=$(defaults read ~/Desktop/MyScriptPrefs MyKey)

printf "After: %s\n" $FOO


More info on the script.


The PrefsEdit GUI tool might interest some readers.

Reply

How to get a value from a plist file using the defaults command?

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.