16

At the moment I'm using this code

  /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $productVersion" "Test/Settings.bundle/Root.plist"

in script part of build phase to put product version in a read only field of the application settings. That field has position 1 (starting from 0) of the preferences array.

I'm asking if it's possibile to use something more robust that 1 to access that field since position can be accidentally changed during development by me or by other developers.

Can I access that element specifying it's identifier regardless of its position?

To better explain my needs, I wrote down an example. I need to put something like 1.2.345 into string node of 2nd dict of array ie I need to change from 0.0.0 to 1.2.345. Is it possible to access to dict node without stating that it's the second in the array? I'm asking for something similar to an xpath expression to be used in PlistBuddy (if any exists).

<?xml version="1.0" encoding="UTF-8"?>
<dict>
<key>PreferenceSpecifiers</key>
<array>
    <dict>
        <key>Title</key>
        <string>Application info</string>
        <key>Type</key>
        <string>PSGroupSpecifier</string>
    </dict>
    <dict>
        <key>DefaultValue</key>
        <string>0.0.0</string>
        <key>Key</key>
        <string>version</string>
        <key>Title</key>
        <string>Version</string>
        <key>Type</key>
        <string>PSTitleValueSpecifier</string>
    </dict>
    <dict>
        <key>DefaultValue</key>
        <string>0</string>
        <key>Key</key>
        <string>build</string>
        <key>Title</key>
        <string>Build</string>
        <key>Type</key>
        <string>PSTitleValueSpecifier</string>
    </dict>
         ...
giampaolo
  • 6,906
  • 5
  • 45
  • 73
  • Depends on the plist (post it?). If you want a keyword referenced entry you should put it in a dictionary instead of an array. – geowar Dec 21 '12 at 16:44
  • 1
    I added an example of plist (not really the plist i'm using, but i have not it available at the moment) – giampaolo Dec 21 '12 at 17:18
  • As long as you use at the top level then you can only access it by index; if you want to access these by specific keywords then you'll have to switch to a dictionary instead. – geowar Dec 21 '12 at 17:21
  • You could put a specific placeholder string (like "don't edit: set by build script") as the string for the preference you want to change and then use that to verify that you're changing the one you intend to be changing (or to search for the right one). – geowar Dec 21 '12 at 17:24
  • Since all the array entry dictionaries have the "Title" entry you could use its value to verify that a specific array entry is the one that you want to modify. I'd try the one at index 1 first and if it's "Title" entry's value isn't "Version" then iterate over all entries until you find it and then set its value. – geowar Dec 21 '12 at 17:34
  • Or just always iterate over all array entries until you find the one whose "Title" entry's value is "Version". – geowar Dec 21 '12 at 17:35
  • could be a good strategy to avoid using straightforward the index. I'm using the index since I following point 8 of the chosen answer of this question: http://stackoverflow.com/questions/6851660/version-vs-build-in-xcode-4 – giampaolo Dec 21 '12 at 17:36
  • need only to now if PlistBuddy can return me number of element in the specified array. – giampaolo Dec 21 '12 at 17:42
  • Assuming someone doesn't nest additional dictionaries: /usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:" ~/Desktop/Root.plist | grep "Dict"|wc -l – geowar Dec 21 '12 at 17:49
  • could you pack all this into a answer? – giampaolo Dec 21 '12 at 18:05
  • Check this stack overflow link [link][1] [1]: http://stackoverflow.com/questions/15573017/how-can-i-add-an-array-to-a-plist-using-plistbuddy/18074038#18074038 – nik Aug 06 '13 at 09:11

2 Answers2

15
#!/bin/tcsh
set productVersion="1.2.345"
set theFile="~/Desktop/PlistBuddy/Root.plist"
set cnt=`/usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:" ${theFile} | grep "Dict"|wc -l`
# echo "the count is: $cnt."
set cnt=`expr "$cnt" '-' '1'`

foreach idx (`seq 0 $cnt`)
    # echo "the index is: $idx."
    set val=`/usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:${idx}:Title" ${theFile}`
    # echo "the value of PreferenceSpecifiers:${idx}:Title: is ${val}."

    if ( "$val" == "Version" ) then
        echo "the index of the entry whose 'Title' is 'Version' is $idx."
        # now set it
        /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:${idx}:DefaultValue $productVersion" ${theFile}

        # just to be sure that it worked
        set ver=`/usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:${idx}:DefaultValue" ${theFile}`
        echo 'PreferenceSpecifiers:$idx:DefaultValue set to: ' $ver
    endif
end
geowar
  • 4,397
  • 1
  • 28
  • 24
7

A little improvement to the geowar's answer. Get product version from Info.plist.

#!/bin/tcsh
set infoPlist="Info.plist"
set version=`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" ${infoPlist}`
set bundleVersion=`/usr/libexec/PlistBuddy -c "Print CFBundleVersion" ${infoPlist}`
set productVersion=$version.$bundleVersion
# echo "the product version is ${productVersion}."

set settingsPlist="Settings.bundle/Root.plist"
set settingsCnt=`/usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:" ${settingsPlist} | grep "Dict"|wc -l`
# echo "the count is: $settingsCnt."
set settingsCnt=`expr "$settingsCnt" '-' '1'`

foreach idx (`seq 0 $settingsCnt`)
    # echo "the index is: $idx."
    set val=`/usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:${idx}:Key" ${settingsPlist}`
    # echo "the value of PreferenceSpecifiers:${idx}:Title: is ${val}."

    if ( "$val" == "version" ) then
        echo "the index of the entry whose 'Key' is 'version' is $idx."
        # now set it
        /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:${idx}:DefaultValue $productVersion" ${settingsPlist}

        # just to be sure that it worked
        set ver=`/usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:${idx}:DefaultValue" ${settingsPlist}`
        echo 'PreferenceSpecifiers:$idx:DefaultValue set to: ' $ver
    endif
end
LordPingvin
  • 163
  • 2
  • 7