2008-09-10
A Unix shell trick
This is the sort of trick where I present the code first and explain it afterwards:
arch=`(PATH=$HOME/bin:/local/bin:$PATH arch || echo unknown) 2>/dev/null`
(This has been slightly modified to keep the line length down; in the
real version, more things are added to $PATH
. Note that this may be
word-wrapped in your browser.)
This sets the $arch
variable to the output of the arch
command,
if there is one to be found in any number of places, and otherwise
gives $arch
the value of 'unknown', all in one line.
It's worth unpacking this into its component parts (somewhat
abbreviated) in order to see how it works:
PATH=$HOME/bin:/local/bin:$PATH arch
- Search for an
arch
command using a temporarily augmented and altered$PATH
. ... || echo unknown
- If we failed to find an
arch
, supply a default value; a command that isn't found is a false condition, just as if the command itself failed. (We assume thatarch
itself will never fail.) (...) 2>/dev/null
- Discard any complaint from the shell about being
unable to find
arch
.
(Using just '$PATH=... arch 2>/dev/null
' wouldn't suppress the
'arch: not found
' error message, because the error message comes from
the shell, not from a theoretical arch
. We have to use a subshell in
order to be able to redirect the shell's own error message.)
This is the kind of thing that makes programming in the Bourne shell fun and interesting, and I say that non-sarcastically.
Sidebar: why I do this
Why I do this requires slightly more explanation. I have a single
generic .profile
that I use on all of the systems I have accounts
on, and on some of them my home directory is shared across multiple
architectures, which means that I need to add an architecture-specific
directory to my $PATH
(for architecture dependent binaries), which
means that I need to know what the local architecture is.
(By local tradition, 'architecture' here includes the operating system as well as the chipset; typical values are things like 'solaris-sparc'.)
There is a vague local tradition that there is an arch
command that
prints out a string suitable for this. However, not all systems follow
this tradition, and not all systems put arch
in the same place, and
sometimes I need to fake it with a $HOME/bin/arch
(if, for example,
I am in a multi-architecture environment that doesn't follow this
tradition). So determining the local architecture requires dealing
with all of these possibilities, hence the one-liner.