How can I add an Array to a Plist using PlistBuddy

2019-02-10 04:32发布

This question is a Sub-Question/Alternative Way to approach what I am trying to do via this question: How can I use PListBuddy to copy an entry from one file to another?

I want to copy an Entry from Plist File A to Plist File B using PlistBuddy through an XCode Build Script, using Bash/Shell. By doing this, I cannot use PlistBuddy's "Copy" function. I must copy each individual entry over with all of it's elements, since you cannot add/set dictionaries, but must interact with PlistBuddy via "Entries".

What I am trying to do is take Plist File A and store its Titles/Values Arrays for a "PSMultiValueSpecifier" element. I am able to grab the elements in the arrays and print them to the screen, but when I go to add them into the destination Plist file B, the arrays are still empty.

Code: (Code to Grab the Entry for Adding)

# Configure the Entry
${PLISTBUDDY} -c "Add PreferenceSpecifiers:$DEST_INDEX dict" ${DEST_PLIST}
${PLISTBUDDY} -c "Add PreferenceSpecifiers:$DEST_INDEX:Type string 'PSMultiValueSpecifier'" ${DEST_PLIST}

# Retrieve the Additional Field Value
preferenceTitle=`$PLISTBUDDY -c "Print PreferenceSpecifiers:$SOURCE_INDEX:Title" $SOURCE_PLIST 2>&1`
preferenceKey=`$PLISTBUDDY -c "Print PreferenceSpecifiers:$SOURCE_INDEX:Key" $SOURCE_PLIST 2>&1`
preferenceDefaultValue=`$PLISTBUDDY -c "Print PreferenceSpecifiers:$SOURCE_INDEX:DefaultValue" $SOURCE_PLIST 2>&1`
preferenceValues=`$PLISTBUDDY -c "Print PreferenceSpecifiers:$SOURCE_INDEX:Values" $SOURCE_PLIST 2>&1`
preferenceTitles=`$PLISTBUDDY -c "Print PreferenceSpecifiers:$SOURCE_INDEX:Titles" $SOURCE_PLIST 2>&1`

Code to Add the new Entry:

# Set the Additional Field Values
${PLISTBUDDY} -c "Add PreferenceSpecifiers:$DEST_INDEX:Title string $preferenceTitle" ${DEST_PLIST}
${PLISTBUDDY} -c "Add PreferenceSpecifiers:$DEST_INDEX:Key string $preferenceKey" ${DEST_PLIST}
${PLISTBUDDY} -c "Add PreferenceSpecifiers:$DEST_INDEX:DefaultValue integer $preferenceDefaultValue" ${DEST_PLIST}
####BORKEN####
${PLISTBUDDY} -c "Add PreferenceSpecifiers:$DEST_INDEX:Values array $preferenceValues" ${DEST_PLIST}
${PLISTBUDDY} -c "Add PreferenceSpecifiers:$DEST_INDEX:Titles array $preferenceTitles" ${DEST_PLIST}
####BORKEN####

Here is a snippet of Code that produces the below data:

echo "#########"
echo "[$THIS] adding $preference: $preferenceDict"
echo "#########"
echo "Source: "`$PLISTBUDDY -c "Print PreferenceSpecifiers:$SOURCE_INDEX:Values" $SOURCE_PLIST`
echo "Source: "`$PLISTBUDDY -c "Print PreferenceSpecifiers:$SOURCE_INDEX:Titles" $SOURCE_PLIST`
echo "#########"
echo "Destination: "`$PLISTBUDDY -c "Print PreferenceSpecifiers:$DEST_INDEX:Values" $DEST_PLIST`
echo "Destination: "`$PLISTBUDDY -c "Print PreferenceSpecifiers:$DEST_INDEX:Titles" $DEST_PLIST`
echo "#########"

Here is the data provided proving that the proper fields are being transported

#########
[addDebugSettingsMenu.bash] adding : Dict {
    Titles = Array {
        Meters
        Feet
    }
    DefaultValue = 1
    Values = Array {
        1
        2
    }
    Key = UserPreferences_UnitsKey
    Type = PSMultiValueSpecifier
    Title = Units
}
#########
Source: Array {     1     2 }
Source: Array {     Meters     Feet }
#########
Destination: Array { }
Destination: Array { }
#########

Please help if you have any knowledge regarding undocumented features of PlistBuddy. The MAN pages are super slim and examples are far and between.

I would like to thank you for reading this and for lending your brains to help me solve this major pain in my neck.

3条回答
倾城 Initia
2楼-- · 2019-02-10 04:49

For something simple like an array of strings, here is code that will combine an arbitrary number of arrays. This example uses the UIAppFonts array common in iOS Info plists.

TMP_NAME=`basename $0`
TMP_DIR=`mktemp -d ${PROJECT_TEMP_DIR}/${TMP_NAME}.XXXXXX` || exit 1
FONTS_PLIST="${TMP_DIR}/Fonts.plist"

/usr/libexec/PlistBuddy -c "Add UIAppFonts array" "${FONTS_PLIST}"

# Iterate through each array, adding to the array entry in the temporary plist
index=0
for arg; do
  status=0
  inner_index=0
  while [ ${status} -eq 0 ]; do
    set +e
    # No easy way to get array length, so keep going until we go out of bounds
    entry=`/usr/libexec/PlistBuddy -c "Print UIAppFonts:${inner_index}" "${arg}" 2> /dev/null`
    status=${?}
    set -e
    if [ ${status} -eq 0 ]; then
      /usr/libexec/PlistBuddy -c "Add UIAppFonts:${index} string ${entry}" "${FONTS_PLIST}"
      index=`expr ${index} + 1`
      inner_index=`expr ${inner_index} + 1`
    fi
  done
done
查看更多
该账号已被封号
3楼-- · 2019-02-10 04:52

It may fix your problem but it is not the right way to implement in larger merging scripts. Check my ans below.

/usr/libexec/PlistBuddy -x -c "Print PreferenceSpecifiers" ${FROM_PLIST} > ${TO_PLIST}
查看更多
做自己的国王
4楼-- · 2019-02-10 04:59

There may be a better way to do this, but I have solved this problem by counting the elements in the source array and then copying them over individually.

${PLISTBUDDY} -c "Add PreferenceSpecifiers:$DEST_INDEX:Titles array" ${DEST_PLIST}    
${PLISTBUDDY} -c "Add PreferenceSpecifiers:$DEST_INDEX:Titles:0 string 'TITLE_1'" 
${DEST_PLIST} ${PLISTBUDDY} -c "Add PreferenceSpecifiers:$DEST_INDEX:Titles:1 string 'TITLE_2'" ${DEST_PLIST} 
etc... 
查看更多
登录 后发表回答