Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Mail Systems
Eclipse Documentation

How To Guides
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Problem Solutions
Privacy Policy




10.1 Shellology

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.

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 distributions.

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:
                   cat ${FOO=`bar`}
  • beware that single builtin substitutions are not performed by a subshell, hence their effect applies to the current shell! See 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’. See Bash Posix Mode, for details.
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 February 2006) 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 (see 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 ‘:’. 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.

  Published under the terms of the GNU General Public License Design by Interspire