Archive for August, 2007

Shell programming: The fu example


Many years ago, back when I thought spending time configuring my Unix environment was a good idea, I wrote a script that I call fu. It helps manage long pathnames and is particularly useful with our tendency to have deep directory structures in perforce:

$ pwd
$ fu master
$ cd `fu master`
$ pwd

As you can see, fu searches up the directory hierarchy (towards root) until it finds a match for its argument.

I think its code provides some interesting points of shell programming that are not always stressed:

# $Header: //depot/home/drj/master/prj/uxutils/fu#3 $
# fu - find up
# finds a file who's name is / where x is specified on the
# command line, and  is some prefix (dirname) of the current
# working directory.



while :
  case "X$d" in
    */) d=`echo "$d"|sed '$s/.$//'`;;
  if test -r "$d/$x"
    echo "$d/$x"
    exit 0
  n=`dirname "$d"`
  if test "X$d" = "X$n"
    exit 4
exit 2

The first things to point out is all the double quotes around variable expansions, like this «”$d”». That’s done so that the variable expands into a single word even when it contains a space. This is almost always what you want. Consider a simple example like «ls $d», if d is the string «foo bar» (which contains a space) then this will ask ls to list the two files «foo» and «bar», which is probably not what you wanted. Of course people that put spaces in their filenames, then pass those names as arguments to Unix programs, then expect it to work, are insane (are you reading this Apple? «Library/Application Support/»). But we do what we can. So unless there are very good reasons why not, every variable expansion gets double quotes around it.

The line that invokes sed, «d=`echo “$d”|sed ‘$s/.$//’`», is pretty typical of string manipulation in shell: tedious, ugly, and sometimes obscure. All it’s doing is stripping a trailing «/» from d, but look how awkward it is. It invokes an external program and probably forks another shell; it could easily be a million times slower than the equivalent code in more traditional compiled language like C or Lisp. You don’t have to do very much of this sort of fiddly manipulation before it becomes very sensible to use a proper language like Python.

«test -r» is evidence of how old the script is (I think). -r tests whether a file is readable, whereas all I care about is existence; clearly I should be using «test -e», but I suspect that at the time I originally wrote the script -e was either not standard or not implemented widely enough. These days I should probably change it.

Those initial Xs in «if test “X$d” = “X$n”» are kind of curious. They’re there to prevent the kind of nonsense that happens if d happens to start with a hyphen and therefore confuse test. If d happened to be «-x» for example, then we would have test -x = something which might confuse test into thinking that it should be executing the -x test (test for an executable file). The version of test on OS X doesn’t suffer this problem, but I’m pretty sure that earlier ones did. I’m pretty sure that the X in «case “X$d”» is there for the same reason, but that’s a bogus reason because case doesn’t suffer this problem.

Hmm. Well, perhaps it would made for some interesting points of shell programming if two of my circumlocutions weren’t made obsolete by progress in Unix utility implementations.

SBCL used in e-counting


Page 21 of ORG’s full report on their observations of the 2007 elections (held for various purposes across the UK) says that SBCL was used for e-Counting in South Bucks. That’s pretty much the only positive thing I’ve found so far. The report just makes me want to weep.

Of course the usual suspects also appear: Windows Server 2003, .Net 2.0, Oracle, Red Hat, Ubuntu (twice!), Apache, Tomcat, Ruby on Rails, Firefox 2.0, Sun JRE.

TextEdit margin hacking


It turns out that if you want to TextEdit to use more of the paper and shrink those ghastly 1 inch margins (which are, frankly, way too big for a lot of purposes) then you can’t do it. Well okay, you can do it by opening the RTF file in a real text editor and hacking the RTF directly. «\margl1440» sets the left margin to 1 inch (72 Adobe approved points in an inch, 20 thingummies in a point).

I don’t know what to be more appalled by. That this 1 inch margin is hard-coded into TextEdit (UTSL); that TextEdit ignores the Page Setup margins; that you have to edit the RTF by hand; that this works?

Can I also just say that if someone had said that the units specified in the RTF file were 127/7200000 of a metre then they would’ve been called insane.