Next: Here-Documents Up: Portable Shell
There are several families of shells, most prominently the Bourne family
and the C shell family which are deeply incompatible. If you want to
write portable shell scripts, avoid members of the C shell family. The
the Shell difference FAQ
(http://www.faqs.org/faqs/unix-faq/shell/shell-differences/) includes a
small history of Posix shells, and a comparison between several of them.
Below we describe some of the members of the Bourne shell family.
Ash is often used on GNU/Linux and BSD systems as a light-weight
Bourne-compatible shell. Ash 0.2 has some bugs that are fixed in
the 0.3.x series, but portable shell scripts should work around
them, since version 0.2 is still shipped with many GNU/Linux
To be compatible with Ash 0.2:
- don't use `$?' after expanding empty or unset variables, or
at the start of an `eval':
echo "Do not use it: $?"
eval 'echo "Do not use it: $?"'
- don't use command substitution within variable expansion:
- beware that single builtin substitutions are not performed by
a subshell, hence their effect applies to the current shell!
Note: Shell Substitutions, item "Command Substitution".
To detect whether you are running Bash, test whether
`BASH_VERSION' is set. To require Posix compatibility, run `set
-o posix'. Note: Bash Posix Mode, for
Bash 2.05 and later
Versions 2.05 and later of Bash use a different format for the
output of the `set' builtin, designed to make evaluating its
output easier. However, this output is not compatible with earlier
versions of Bash (or with many other shells, probably). So if you
use Bash 2.05 or higher to execute `configure', you'll need to use
Bash 2.05 for all other build tasks as well.
The Korn shell is compatible with the Bourne family and it mostly
conforms to Posix. It has two major variants commonly called
`ksh88' and `ksh93', named after the years of initial release. It
is usually called `ksh', but is called `sh' on some hosts if you
set your path appropriately.
Solaris systems have three variants: `/usr/bin/ksh' is `ksh88'; it
is standard on Solaris 2.0 and later. `/usr/xpg4/bin/sh' is a
Posix-compliant variant of `ksh88'; it is standard on Solaris 9
and later. `/usr/dt/bin/dtksh' is `ksh93'. Variants that are not
standard may be parts of optional packages. There is no extra
charge for these packages, but they are not part of a minimal OS
install and therefore some installations may not have it.
Starting with Tru64 Version 4.0, the Korn shell `/usr/bin/ksh' is
also available as `/usr/bin/posix/sh'. If the environment
variable `BIN_SH' is set to `xpg4', subsidiary invocations of the
standard shell conform to Posix.
A public-domain clone of the Korn shell called `pdksh' is widely
available: it has most of the `ksh88' features along with a few of
its own. It usually sets `KSH_VERSION', except if invoked as
`/bin/sh' on OpenBSD, and similarly to Bash you can require Posix
compatibility by running `set -o posix'. Unfortunately, with
`pdksh' 5.2.14 (the latest stable version as of January 2007)
Posix mode is buggy and causes `pdksh' to depart from Posix in at
least one respect:
$ echo "`echo \"hello\"`"
$ set -o posix
$ echo "`echo \"hello\"`"
The last line of output contains spurious quotes. This is yet
another reason why portable shell code should not contain
`"`...\"...\"...`"' constructs (Note: Shell Substitutions).
To detect whether you are running `zsh', test whether
`ZSH_VERSION' is set. By default `zsh' is _not_ compatible with
the Bourne shell: you must execute `emulate sh', and for `zsh'
versions before 3.1.6-dev-18 you must also set `NULLCMD' to `:'.
Note: Compatibility, for details.
The default Mac OS X `sh' was originally Zsh; it was changed to
Bash in Mac OS X 10.2.
The following discussion between Russ Allbery and Robert Lipe is
The GNU assumption that `/bin/sh' is the one and only shell leads
to a permanent deadlock. Vendors don't want to break users'
existing shell scripts, and there are some corner cases in the
Bourne shell that are not completely compatible with a Posix
shell. Thus, vendors who have taken this route will _never_
(OK..."never say never") replace the Bourne shell (as `/bin/sh')
with a Posix shell.
This is exactly the problem. While most (at least most System
V's) do have a Bourne shell that accepts shell functions most
vendor `/bin/sh' programs are not the Posix shell.
So while most modern systems do have a shell _somewhere_ that
meets the Posix standard, the challenge is to find it.
automatically generated by info2www