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 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.
To be compatible with Ash 0.2:
foo= false $foo echo "Do not use it: $?" false eval 'echo "Do not use it: $?"'
cat ${FOO=`bar`}
BASH_VERSION
is set. To require
Posix compatibility, run ‘set -o posix’. See Bash Posix Mode, for details.
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.
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 February 2006)
Posix mode is buggy and causes pdksh to depart from Posix in
at least one respect:
$ echo "`echo \"hello\"`" hello $ set -o posix $ echo "`echo \"hello\"`" "hello"
The last line of output contains spurious quotes. This is yet another
reason why portable shell code should not contain
"`...\"...\"...`"
constructs (see Shell Substitutions).
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 ‘:’. See 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 worth reading:
Russ Allbery:
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.
Robert Lipe:
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.