Unix Shells compared
I sent an earlier version of
this opinionated summary of Unix shells to
the pragmatic programmers' list last Friday.
This raises a question: what are the substantive differences between
the various shells?
I'm not saying that i'm about to switch. However, a description of
features which prompted other people to choose their shells, or
perhaps the general mindset that each shell promotes would be helpful
My executive summary:
- zsh, bash, ksh — best of breed
- es — coulda been a contender
- csh — for non-programmers and twisted minds
Way more details than most of you will want to read:
I have used Unix and shells, in various forms, since about
1976. So, I started with the shell that preceded Bourne,
not often mentioned even in places that talk about the history
of Unix shells...
I worked at Sun for ten years, starting in 1986. So I actually
did have to use csh for a year or so, until a copy of the Korn
shell ksh was made available internally. I have always hated
csh. Csh added some good ideas to the Unix/shell world ("~" and
command line history), but was horribly badly implemented and
buggy, and the programming syntax that went with it was and is
I think it significant that the SECOND google entry in a
search for "programming in CSH" leads to a paper called
Csh Programming Considered Harmful...
So, if you're the type that would think it normal, while at
a command prompt, to write a four-or-five line for loop with
an if statement in it, you almost certainly do not want to be
The Bourne shell has a slightly strange, but clean syntax,
and it is what the majority of shell scripts are written for.
The guts of most shell scripts will work with any of ksh, zsh
One of the things that was done at Sun while I was there was
that they (Neil Smithline, mostly) crammed a version of ksh
(pdksh, a public domain clone) into their debugger dbx, to give
it a decent scripting ability. This was just a bit before I first
noticed the first versions of Python. 1988 or so?
When I left Sun, I went to Apple and worked there for six years.
The last four of those years involved the NeXT merger (1997),
and I worked on tools for what became Mac OS X; this meant that I
worked on OpenStep for a while. That was NeXT's window GUI
environment and frameworks that could be run on their own native
(Mach-based) Unix implementation, but were also portable and
could be run on top of other OSes, namely Solaris, HPUX, and
even Windows NT. So I typically had to switch among all of those
OSes to test things. The only shell that they had available on
all of those environments was zsh, so I started using that,
and have stuck with it ever since.
Zsh and bash have similar capabilities, but I prefer zsh for
a few of its extensions in these areas:
- its "tilde-naming" substitution (put a pathname into a
zsh variable or environment var, and then you can use
~varname to refer to it — and zsh can use that short
name in its prompt if desired);
- the filename-glob-matching syntax ("**/bar" looks "all
the way down", "foo^bar" matches foo but not bar, and
you can restrict the match to (/) directories, (*)
executable files, or (w) writable files, etc.);
- "autoload" shell functions;
- the way it handles variable expansion (e.g., the
shorthand ways that you can control SH_WORD_SPLIT).
I think all of the relatively modern shells support the
readline-style input history; zsh can also use the csh-style
history substitution syntax (!!, ^^ et al).
IMHO, the most interesting shell of all the ones I've seen was
"es", the "extensible shell". Basically, a functional programming
language married to a minimal shell syntax, and with as many things
made extensible as Haahr and Rakitzis could think of. It derived from
"rc", the minimalist shell for the Plan 9 OS from Bell Labs. See
These days, most scripts that I write are short zsh scripts, and
longer Python scripts.