John Lockwood

Q: How do I add to this plist?

There is a plist file that I want to add an entry to, if the entry already exists I also don't want to cause a duplicate of it to appear. This is what the plist file current would look like.

 

<?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">
<array>
  <dict>
  <key>Folder Name</key>
  <string>Birthday</string>
  </dict>
  <dict>
  <key>Folder Name</key>
  <string>Announcements</string>
  </dict>
  <dict>
  <key>Folder Name</key>
  <string>Photos</string>
  </dict>
  <dict>
  <key>Contains Original Stationery</key>
  <string>yes</string>
  <key>Folder Name</key>
  <string>Stationery</string>
  </dict>
  <dict>
  <key>Folder Name</key>
  <string>Sentiments</string>
  </dict>
</array>
</plist>

 

I want to add another entry of

 

<dict>
<key>Folder Name</key>
<string>My Folder</string>
</dict>

 

So the new file should look like

 

<?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">
<array>
  <dict>
  <key>Folder Name</key>
  <string>My Folder</string>
  </dict>
  <dict>
  <key>Folder Name</key>
  <string>Birthday</string>
  </dict>
  <dict>
  <key>Folder Name</key>
  <string>Announcements</string>
  </dict>
  <dict>
  <key>Folder Name</key>
  <string>Photos</string>
  </dict>
  <dict>
  <key>Contains Original Stationery</key>
  <string>yes</string>
  <key>Folder Name</key>
  <string>Stationery</string>
  </dict>
  <dict>
  <key>Folder Name</key>
  <string>Sentiments</string>
  </dict>
</array>
</plist>

 

In OS X as standard there are two commands for modifying plist files, these are /usr/bin/defaults and /usr/libexec/PlistBuddy I would be happy to use either or any other built-in command but ideally it needs to be something built-in.

 

Many thanks for any help.

Posted on Aug 8, 2014 4:00 PM

Close

Q: How do I add to this plist?

  • All replies
  • Helpful answers

  • by baltwo,

    baltwo baltwo Aug 8, 2014 3:55 PM in response to John Lockwood
    Level 9 (62,256 points)
    Aug 8, 2014 3:55 PM in response to John Lockwood

    Mucking around with plists is a delicate matter and is an esoteric art. Accourding to the manpage, something along these lines might work. Copy the plist to the Desktop and play around with it until you ascertain the correct syntax.

     

    PlistBuddy Add  :CFBundleDocumentTypes:0 dict "<key>Folder Name</key>  <string>My Folder</string>"

     

    Alternatively, open the file in a text editor or use the nano command, add the lines, and save it as a plist. Ensure that the permissions remained as the original and just replace it with the modified one.

  • by Mark Jalbert,Helpful

    Mark Jalbert Mark Jalbert Aug 8, 2014 5:06 PM in response to John Lockwood
    Level 5 (4,649 points)
    Aug 8, 2014 5:06 PM in response to John Lockwood
    /usr/libexec/PlistBuddy -c "add dict:'Folder Name' string 'My Folder'" path/to/foo.plist
    

    The defaults command is not liking your xml file but PlistBuddy to the rescue.

  • by baltwo,

    baltwo baltwo Aug 9, 2014 11:48 AM in response to Mark Jalbert
    Level 9 (62,256 points)
    Aug 9, 2014 11:48 AM in response to Mark Jalbert

    Thanks for popping in. As I said, esoteric and not readily discernible from the manpage examples, which aren't at all.

  • by John Lockwood,

    John Lockwood John Lockwood Aug 11, 2014 4:24 AM in response to Mark Jalbert
    Level 6 (9,349 points)
    Servers Enterprise
    Aug 11, 2014 4:24 AM in response to Mark Jalbert

    Thank you both for your responses. I tried Mark's answer first and it added a new entry exactly like I needed. I would now like a similar method to delete the same entry that your answer added. This will enable a tidy uninstall process to be achieved.

     

    For what its worth, I had just prior to both your responses come up with a quick and dirty solution to both adding and removing entries which involves running a Perl command. However I feel PlistBuddy is likely to be a more robust solution.

     

    Here was my Perl command to add an entry -

     

    perl -i -pe 'BEGIN{undef $/;} s/<\/array>.*<\/plist>/\t<dict>\n\t\t<key>Folder Name<\/key>\n\t\t<string>My Folder<\/string>\n\t<\/dict>\n<\/array>\n<\/plist>/smg' "/Library/Application Support/Apple/Mail/Stationery/Apple/Contents/Resources/TableOfContents.plist"
    

     

    and the corresponding Perl to remove the same entry -

     

    perl -i -pe 'BEGIN{undef $/;} s/\n\t<dict>\n\t\t<key>Folder Name<\/key>\n\t\t<string>My Folder<\/string>\n\t<\/dict>//smg' "/Library/Application Support/Apple/Mail/Stationery/Apple/Contents/Resources/TableOfContents.plist"
    
  • by VikingOSX,

    VikingOSX VikingOSX Aug 11, 2014 6:34 AM in response to John Lockwood
    Level 7 (21,061 points)
    Mac OS X
    Aug 11, 2014 6:34 AM in response to John Lockwood

    John,

     

    Did you try Mark’s syntax substituting delete for add, after making an appropriate backup of your plist?

  • by John Lockwood,

    John Lockwood John Lockwood Aug 11, 2014 9:17 AM in response to VikingOSX
    Level 6 (9,349 points)
    Servers Enterprise
    Aug 11, 2014 9:17 AM in response to VikingOSX

    VikingOSX wrote:

     

    John,

     

    Did you try Mark’s syntax substituting delete for add, after making an appropriate backup of your plist?

    Yes,

     

    /usr/libexec/PlistBuddy -c "delete dict:'Folder Name' string 'My Folder'" path/to/foo.plist

     

    (with my file) generates the error message

     

    Delete: Entry. "dict:Folder Name", Does Not Exist

  • by Mark Jalbert,Helpful

    Mark Jalbert Mark Jalbert Aug 11, 2014 2:03 PM in response to John Lockwood
    Level 5 (4,649 points)
    Aug 11, 2014 2:03 PM in response to John Lockwood

    If you print your plist with PlistBuddy you'll get a better idea of the files structure.

    /usr/libexec/PlistBuddy -c "Print" path/to/foo.plist 
    

    You are adding an element to an array. To remove an element of the array you must reference the element by its number.

    /usr/libexec/PlistBuddy -c "Delete 0:" path/to/foo.plist 
    
  • by baltwo,

    baltwo baltwo Aug 11, 2014 2:29 PM in response to Mark Jalbert
    Level 9 (62,256 points)
    Aug 11, 2014 2:29 PM in response to Mark Jalbert

    The problem with that is that PlistBuddy's Print doesn't reveal the element's number if there are multiple ones in an array. Only something like Property List Editor, XCode, or PlistEditor can do that. Then, there's the problem with the syntax for each dict element. Poorly written manpages don't help.

     

    E.g., in the user's .GlobalPrefs there's a text substitution array with dict entries and no element numbers. Here's a portion:

     

    Dict {        NSUserDictionaryReplacementItems = Array {

            Dict {

                replace = c/o

                on = 1

                with = ℅

            }

            Dict {

                replace = ...

                on = 1

                with = …

            }

            Dict {

                replace = 1/2

                on = 1

                with = ½

            }

        }

    }

  • by twtwtw,

    twtwtw twtwtw Aug 11, 2014 4:46 PM in response to John Lockwood
    Level 5 (4,935 points)
    Aug 11, 2014 4:46 PM in response to John Lockwood

    This is one of the things that applescript is good at:

     

    tell application "System Events"

      set markupFile to property list file "/path/to/XML file.xml"

      tell markupFile

      make new property list item at beginning of property list items with properties {value:{|folder name|:"My Folder"}}

      end tell

    end tell

     

    If you need to run it from the command line you can use osascript to call a precompiled script or build the script line-by-line.

  • by John Lockwood,

    John Lockwood John Lockwood Aug 12, 2014 2:27 AM in response to Mark Jalbert
    Level 6 (9,349 points)
    Servers Enterprise
    Aug 12, 2014 2:27 AM in response to Mark Jalbert

    Thanks again Mark, I can see how that will work by referencing a specific entry number i.e. first, second etc. however this then leads on to the next issue of how to determine in a script which entry number matches a particular string value.

     

    My Perl solution just matches the string and enclosing tags and does not care about what position - first, second, last, it is. Obviously one cannot assume a particular entry will always be in a particular position.

     

    Thanks everyone for their contributions.

  • by Upshot IT,

    Upshot IT Upshot IT Oct 8, 2015 8:27 AM in response to John Lockwood
    Level 1 (0 points)
    Oct 8, 2015 8:27 AM in response to John Lockwood

    What I'm trying to do is similar.

     

    I need to create a simple shell script to call on PlistBuddy to add a new string (/System/Library/CoreServices/Menu Extras/Script Menu.menu) to the existing "menuExtras" array in the file from the screenshot below.

     

    The syntax is killing me. I just can't find the right combination from the examples I've found. This is a copy of the real plist file to test first.

     

    The purpose is to enable the Script Menu in the menubar when one of my users installs a new AppleScript from Casper Suite's Self Service app.

     

    Screen Shot 2015-10-08 at 10.08.05 AM.png

  • by VikingOSX,

    VikingOSX VikingOSX Oct 8, 2015 9:19 AM in response to Upshot IT
    Level 7 (21,061 points)
    Mac OS X
    Oct 8, 2015 9:19 AM in response to Upshot IT

    /usr/libexec/plistbuddy ~/Desktop/_Casper/_PLIST_FILES/com.apple.systemuiserver.plist

     

    Command: add :menuExtras: string /System/Library/CoreServices/Menu Extras/Script Menu.menu

    Command: print :menuExtras

    Command: Save

    Command: Exit