Surely I haven’t been doing shell scripting for 30 years?!? Well, now that I think
about it, I suppose I have, although it was only in a small way at first. (The early
Unix shells, before the Bourne shell, were very primitive by modern standards, and
writing substantial scripts was difficult. Fortunately, things quickly got better.)
In recent years, the shell has been neglected and underappreciated as a scripting language. But even though it was Unix’s first scripting language, it’s still one of the best.
Its combination of extensibility and efficiency remains unique, and the improvements made to it over the years have kept it highly competitive with other scripting
languages that have gotten a lot more hype. GUIs are more fashionable than command-line shells as user interfaces these days, but scripting languages often provide
most of the underpinnings for the fancy screen graphics, and the shell continues to
excel in that role.
The shell’s dependence on other programs to do most of the work is arguably a
defect, but also inarguably a strength: you get the concise notation of a scripting language plus the speed and efficiency of programs written in C (etc.). Using a common, general-purpose data representation—lines of text—in a large (and extensible)
set of tools lets the scripting language plug the tools together in endless combinations. The result is far more flexibility and power than any monolithic software package with a built-in menu item for (supposedly) everything you might want. The early
success of the shell in taking this approach reinforced the developing Unix philosophy of building specialized, single-purpose tools and plugging them together to do
the job. The philosophy in turn encouraged improvements in the shell to allow doing
more jobs that way.
Shell scripts also have an advantage over C programs—and over some of the other
scripting languages too (naming no names!)—of generally being fairly easy to read
and modify. Even people who are not C programmers, like a good many system
administrators these days, typically feel comfortable with shell scripts. This makes
shell scripting very important for extending user environments and for customizing
This is the Title of the Book, eMatter Edition
Indeed, there’s a “wheel of reincarnation” here, which I’ve seen on several software
projects. The project puts simple shell scripts in key places, to make it easy for users
to customize aspects of the software. However, it’s so much easier for the project to
solve problems by working in those shell scripts than in the surrounding C code, that
the scripts steadily get more complicated. Eventually they are too complicated for the
users to cope with easily (some of the scripts we wrote in the C News project were
notorious as stress tests for shells, never mind users!), and a new set of scripts has to
be provided for user customization…
For a long time, there’s been a conspicuous lack of a good book on shell scripting.
Books on the Unix programming environment have touched on it, but only briefly,
as one of several topics, and the better books are long out-of-date. There’s reference
documentation for the various shells, but what’s wanted is a novice-friendly tutorial,
covering the tools as well as the shell, introducing the concepts gently, offering
advice on how to get the best results, and paying attention to practical issues like
readability. Preferably, it should also discuss how the various shells differ, instead of
trying to pretend that only one exists.
This book delivers all that, and more. Here, at last, is an up-to-date and painless
introduction to the first and best of the Unix scripting languages. It’s illustrated with
realistic examples that make useful tools in their own right. It covers the standard
Unix tools well enough to get people started with them (and to make a useful reference for those who find the manual pages a bit forbidding). I’m particularly pleased
to see it including basic coverage of awk, a highly useful and unfairly neglected tool
which excels in bridging gaps between other tools and in doing small programming
jobs easily and concisely.
I recommend this book to anyone doing shell scripting or administering Unixderived systems. I learned things from it; I think you will too.
This is the Title of the Book, eMatter Edition
Here is a shorter solution to the telephone-directory sorting problem, using a temporary file and system( ) instead of an awk pipeline:
tmpfile = "/tmp/telephone.tmp"
for (name in telephone)
print name "t" telephone[name] > tmpfile
system("sort < " tmpfile)
The temporary file must be closed before the call to system( ) to ensure that any buffered output is properly recorded in the file.
There is no need to call close( ) for commands run by system( ), because close( ) is
only for files or pipes opened with the I/O redirection operators and getline, print,
The system( ) function provides an easy way to remove the script’s temporary file:
system("rm -f " tmpfile)
The command passed to system( ) can contain multiple lines:
It produces the output expected when copying the here document to standard
Because each call to system( ) starts a fresh shell, there is no simple way to pass data
between commands in separate calls to system( ), other than via intermediate files.
There is an easy solution to this problem—use an output pipeline