So I don’t know about any of you, gentle readers, but ‘defaults’ really gives me the shits sometimes.
Exhibit A:
/ $ defaults read /Library/Preferences/com.apple.loginwindow.plist 2007-11-21 13:12:04.288 defaults[97501:10b] Domain com.apple.loginwindow.plist does not exist / $ defaults read /Library/Preferences/com.apple.loginwindow (snip actual working output)
Exhibit B:
/ $ cd /Library/Preferences /Library/Preferences $ defaults read ./com.apple.loginwindow.plist 2007-11-21 13:13:24.327 defaults[97540:10b] Domain ./com.apple.loginwindow.plist does not exist /Library/Preferences $ defaults read ./com.apple.loginwindow 2007-11-21 13:13:25.799 defaults[97546:10b] Domain ./com.apple.loginwindow does not exist
This really annoys me, that ‘defaults’ firstly doesn’t accept the full path to the plist, when other tools like ‘launchctl’ do, and requires that you strip off the “.plist” from the end, and secondly, that you can’t use relative paths.
This annoyed me so much that I decided to finally do something about it. This function resolves both problems.
function defread { defaults read $(echo "$@" | sed "s|\./|`pwd`/|g" | sed "s|.plist||g"); }
And now we can do:
/ $ defread /Library/Preferences/com.apple.loginwindow.plist / $ cd /Library/Preferences /Library/Preferences $ defread ./com.apple.loginwindow.plist
or even:
/Library/Preferences $ defread ./com.apple.loginwindow.plist SHOWFULLNAME 1
mmmm.
Cool, yeah, I’ve had the same problem.
Another plist-type function I wrote:
plv () {
plutil -convert xml1 -o /dev/fd/1 $1 | /usr/bin/pl
}
useful to view a property list since /usr/bin/pl (even in Leopard) still doesn’t support binary property lists.
I’m just as happy using the plistlib from Python, myself, compared to what you get from `defaults`. I haven’t tried the latest version that ships with Python 2.5.1, but if it has developed support for binary plists, that’d make it even better.
But, yes, `defaults` even with its warts, still has an edge at the command line so your function is a good idea.
I also tend to use defaults using only the domain syntax:
% defaults read com.apple.loginwindow
And plutil for plist file manipulation. Naturally, it needs a wrapper too! Here’s the one I use:
#!/bin/bash
# plcat, cat binary plists as XML.
# By Tom Harrington, June 2005. .
# Usage:
# plcat
# or:
# plcat $tempfile
# convert temp file in place
/usr/bin/plutil -convert xml1 $tempfile
else
# plutil doesn't write to stdout, so the result gets saved and then accessed.
/usr/bin/plutil -convert xml1 -o $tempfile $1;
fi
if [ -e $tempfile ]; then
/bin/cat $tempfile;
/bin/rm -i -f $tempfile;
fi
Nicholas’ function looks neater, but isn’t pl deprecated? As you can see from the date, Tom wrote the above script for a not-so-current version of OS X.
Whoops, major html tag gobbling. I’ll try the code again:
#!/bin/bash
# plcat, cat binary plists as XML.
# By Tom Harrington, June 2005. .
# Usage:
# plcat
# or:
# plcat $tempfile
# convert temp file in place
/usr/bin/plutil -convert xml1 $tempfile
else
# plutil doesn't write to stdout, so the result gets saved and then accessed.
/usr/bin/plutil -convert xml1 -o $tempfile $1;
fi
if [ -e $tempfile ]; then
/bin/cat $tempfile;
/bin/rm -i -f $tempfile;
fi
By the way, despite the usage comment, the regular old “plcat file” syntax also works.
heh.
So I’ve been writing heaps of Python since moving to Google, (well we did hire Guido, what do you expect? :) ) and have been doing a lot of plistlib work, as well as dealing with the Ruby plist stuff.
Why has no-one reverse engineered the binary format yet?
Is it just that it’s really easy to coerce an XML parser into parsing the xml1 format and no-one could be bothered doing the work?
Is it that Apple themselves don’t seem to have documented it?
I’m sick of wrapping plutil -convert commands in try: except: or begin rescue blocks and it’s not always appropriate. Sometimes you want to read the plist before requesting elevated privileges to make changes to it.
Now I think about it, I’ve actually started writing a whole bunch of Ruby wrappers that use PlistBuddy instead, now that it’s at /usr/libexec/ in Leopard. It really annoys me how ‘defaults’ logs to syslog every time you query for a non-existent key, no matter where you redirect stdout/stderr.