Using 'defaults delete' command with com.apple.dock

I have been using the "defaults" command in my scripts to add an icon to a user's dock after a new application has been installed. But now, I'm having trouble trying to figure out how to remove an icon from the dock using the command line. For adding an icon, I use:

defaults write com.apple.dock persistent-apps -array-add '<dict><key>tile-data</key><dict><key>file-data</key><dict>
<key>_CFURLString</key><string>/Applications/NewApp/Program.app
</string><key>_CFURLStringType</key><integer>0</integer>
</dict></dict></dict>'
(take out all the carriage returns and spaces. I had to put them in here for the line to show properly on the post)

This works great for adding an icon. But, I cannot seem to write something similar using "defaults delete"

Any help is appreciated.

Thanks,
-Steve

PowerMac G5 Mac OS X (10.4.7)

Posted on Sep 25, 2006 11:49 AM

Reply
4 replies

Sep 26, 2006 7:22 PM in response to JoMyKe4

Hi Steve,
Please don't take my lack of immediate response as a lack of interest. In fact, your question answers one of mine that I didn't even know I had when started the investigation. I want to mount my users Active Directory home directory and display it in the Dock as Tiger can do automatically.

Unfortunately the initial investigation was very brief. It doesn't look to me as though the "defaults" command has the capability of making the kind of surgical deletion you want. I see only one possible answer and that is to use the power of UNIX text editing. We could use a stream editor like sed or awk and simply remove the unwanted lines. I see two possibilities for how to write the results back to the property list. The stream editor could keep the array, minus the dict you don't want, and use the defaults command to write that back into the property list. Alternatively, you could use the text editor to write the entire file, minus the unwanted array element of course.

The script that controls the stream editor won't be that simple. It will have to "read ahead" to determine whether to keep an array element. I'll take a shot at writing that and post back, whether I can or not. That is of course if you're interested in that approach.

There's one l can mention now. In Tiger, the defaults command writes the result as a binary property list. It will have to be converted to XML before a UNIX stream editor can operate on it. That command would look like the following:

plutil -convert xml1 <path2plist>

Nothing happens if the file is already in XML format.
--
Gary
~~~~
Adding sound to movies would be like putting
lipstick on the Venus de Milo.
-- actress Mary Pickford, 1925

Sep 26, 2006 10:36 PM in response to JoMyKe4

Hi Steve,
Alright, I think I've gotten it to work. I decided to work in the "native format" of the defaults command so that I could read the "persistent-apps" array, alter it and then use defaults to write it directly back into "persistent-apps". The awk command loops through each top-level array element looking for the _CFURLString key and checks to see if the name/value pair match a string. In this example the string is "zzzz". You can replace that with a regular expression that matches whatever you want to cut out. If a match occurs with the string you choose, that array element is omitted. The rest should be copied faithfully. Here's the command:

defaults write com.apple.dock persistent-apps "$( defaults read com.apple.dock persistent-apps | awk 'BEGIN{ ARRAY = "("; ELEM = "" } / {/{ while ( $0 !~ /^ }/ ) { if ( ELEM == "" ){ ELEM = $0 } else { ELEM = ELEM "\n" $0 } if ( $0 ~ "_CFURLString\"" && $0 !~ /zzzz/ ){ FOUND = "true" } getline } ELEM = ELEM "\n" $0; if ( FOUND == "true" ){ ARRAY = ARRAY "\n" ELEM }; FOUND = "false"; ELEM = "" } END{ sub( /,[^\n]*$/, "", ARRAY); print ARRAY; print }' )"

Under test conditions, I was surprised at how well it worked. I was able to copy the array from one property list to another, deleting what I wanted from it in the process. It will even delete multiple elements of the array, which is something for which you need to watch out. Make sure that the regular expression that you use instead of "zzzz" matches only elements that you want to delete. Also, make sure you have a backup during testing.
--
Gary
~~~~
Nothing increases your golf score like witnesses.

Sep 28, 2006 11:55 AM in response to Gary Kerbaugh

I couldn't really get this to work right. It may just be the syntax I'm using. I'm not a scripter by trade. I mostly script out of necessity. When I replace the string "zzzz" with a program, say, "Photoshop", the awk process runs at 100% CPU usage and never seems to finish. I've let it run (on my dual 2GHz G5) for 20 minutes and it still never finishes. Would sed be any faster? Using something like

sed -e '/Photoshop/d'

Or, would editing an XML file make it easier? Use the plutil to convert the dock pref to XML, find the string you want removed between the opening <dict> and closing </dict> and remove the entire <dict> </dict> section? And, if needed, convert it back to binary?

Thanks for pointing me in the right direction!

-Steve

Sep 28, 2006 4:02 PM in response to JoMyKe4

Hi Steve,
If it froze then the code isn't robust against problems. In this case the problem is the web. The command has four spaces in a row in two of the matches. However, the browser smashes that down into a single space. I never understood that aspect of HTML but I know about it and should have considered it. I will replace the spaces with capital Xs. If you replace the Xs with regular spaces, the command should work:

defaults write com.apple.dock persistent-apps "$( defaults read com.apple.dock persistent-apps | awk 'BEGIN{ ARRAY = "("; ELEM = "" } /^XXXX{/{ while ( $0 !~ /^XXXX}/ ) { if ( ELEM == "" ){ ELEM = $0 } else { ELEM = ELEM "\n" $0 } if ( $0 ~ "_CFURLString\"" && $0 !~ /zzzz/ ){ FOUND = "true" } getline } ELEM = ELEM "\n" $0; if ( FOUND == "true" ){ ARRAY = ARRAY "\n" ELEM }; FOUND = "false"; ELEM = "" } END{ sub( /,[^\n]*$/, "", ARRAY); print ARRAY; print }' )"

In some sense that is poor coding but in the default syntax of the "defaults" command, the only way to determine depth is by how far something is indented. It would have been far more robust to actually count the number of opening parentheses and keep track of the depth but that would have been more complex to code. If I have time, I'll look into changing that.

I assume that the reason the command hung is that it went into an infinite loop. I've also added a carat, '^', in front of the first group of four spaces that will keep that from happening. When typed correctly the command works without it but now it will fail without going into an infinite loop.
--
Gary
~~~~
United Nations, New York, December 25. The peace and joy of the Christmas season was marred by a proclamation of a general strike of all the military forces of the world. Panic reigns in the hearts of all the patriots of every persuasion. Meanwhile, fears of universal disaster sank to an all-time low over the world.
-- Isaac Asimov

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

Using 'defaults delete' command with com.apple.dock

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