Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I have some plist files on Mac OS X that I would like to shrink. They have a lot of <dict> with <key> and values. One of these keys is a thumbnail which has a <data> value with base64 encoded binary (I think). I would like to remove this key and value.

I was thinking this could maybe be done by sed, but I don't really know how to use it and it seems like sed only works on a line-by-line basis?

Either way I was hoping someone could help me out. In the file I would like to delete everything that matches the following pattern or something close to that:

<key>Thumbnail<\/key>[^<]*<\/data>

In the file it looks like this:

            // Other keys and values

            <key>Thumbnail</key>
            <data>
            TU0AKgAAOEi25Pqx3/ip2fak0vOdzPCVxu2RweuPv+mLu+mIt+aGtuaEtOSB

            ...

            dCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA=
            </data>

            // Other keys and values

Anyone know how I could do this? Also, if there are any better tools that I can use in the terminal to do this, I would like to know about that as well :)

share|improve this question
add comment

4 Answers 4

There are two utilities available on the command line specifically devoted to working with preference list files: defaults (in /usr/bin) and PlistBuddy in (/usr/libexec).

Still using sed:

sed does allow a multiple line delete using the D instead of the d flag.

eg. sed -e '/<key>Thumbnail<\/key>/, /<\/data>/D' < /PATH/TO/FILE.txt removes all instances of the key Thumbnail and it's associated data.

Using defaults:

defaults delete /PATH/TO/PLIST "Thumbnail". Do not include the .plist extension as part of the path. Also, this will only work on root level items in a .plist, so if the Thumbnail key is inside another array or dict it won't work.

Using PlistBuddy:

/usr/libexec/PlistBuddy -c "Delete :Thumbnail" /PATH/TO/PLIST.plist. If the Thumbnail key is nested, you can append the path before it if you know it. eg. PlistBuddy -c "Delete :User:Thumbnail" if the Thumbnail entry was in a User dictionary.

share|improve this answer
add comment

XMLStarlet is an awesome command line tool for manipulating XML. The main problems with it are 1) it's a very complex tool (since it does very complex jobs), and 2) you'd probably have to build it for OS X yourself.

share|improve this answer
add comment

use awk, not sed

$ cat file
asdkf
asdklf
            // Other keys and values

            <key>Thumbnail</key>
            <data>
            TU0AKgAAOEi25Pqx3/ip2fak0vOdzPCVxu2RweuPv+mLu+mIt+aGtuaEtOSB

            ...

            dCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA=
            </data>

            // Other keys and values

ksdf

$ awk 'BEGIN{RS="</data>"} /<key>/{ gsub("<key>.*</key>|<data>.*","") }1' file
asdkf
asdklf
            // Other keys and values





            // Other keys and values

ksdf

the statement says, use </data> as record separator, then replace tags <key> and <data> with nothing, when <key> is found in the record

share|improve this answer
add comment

It might be possible to do this with sed, but it would be difficult. Perl could do this more easily. The guts of the perl script would be:

undef $/; # This allows reading in of all lines in one swoop

$contents = <>; # Read in contents of file (specified on command line)

$contents = s{<key>Thumbnail</key>.*?</data>}{}s;

print $contents;

If you had the above in a perl script called change.plx and you had your data in a file called keyfile, then you could fix up that file by doing:

$ perl change.plx keyfile > /tmp/$$ && cat /tmp/$$ > keyfile && rm /tmp/$$

Of course, make sure you have a backup of any file that you do this to. It's possible to do all this work on multiple files with a single one line perl program on the command line like this:

$ perl -p0777i -e 's{<key>Thumbnail</key>.*?</data>}{}s;' file file file ...

Marnix

share|improve this answer
    
Something was deleted from my regular expressions. I'm new to this site and I'm guessing that any html-like expressions need to be escaped. The regular expression was supposed to be (hopefully it will work in this comment): s{Thumbnail.*?</data>}{}s Marnix –  Marnix A. van Ammers Apr 7 '10 at 17:32
1  
You need to indent your code example with 4 spaces. Think there also is a code button above the editor that you can click while having your code selected. –  Svish Apr 7 '10 at 20:51
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.