Bash is a from-scratch rewrite of the Bourne shell, made for the GNU project so that free systems would have a command interpreter not tied to AT&T’s proprietary code. From that starting point — replacing an existing program without changing its observable behaviour — follows much of Bash’s technical design, including the parts that make portable scripting harder today.
Context
Stephen Bourne’s shell (sh), shipped with Seventh Edition Unix in 1979, was for years the reference interpreter for system scripts. Its source falls under AT&T’s Unix licence and cannot be redistributed freely. The GNU project has been rebuilding a complete operating system from free components since 1984, and a shell is a mandatory piece.
Brian Fox began writing Bash in 1988 and released the first beta, 0.99, on 8 June 1989 (Chet Ramey’s article). The name — Bourne-Again SHell — states the goal: redo the Bourne shell, not extend its source. Maintenance passed to Chet Ramey between 1992 and 1994, and Ramey is still its primary maintainer.
The current stable release is Bash 2.05a, announced in November 2001 (info-gnu). It is mostly a bug-fix release, an intermediate step before work on larger features.
The rewrite problem
Rewriting a language that was never formally documented means chasing a moving target. No public standard existed for the Bourne shell’s behaviour: what defined it was what Bourne’s code did, edge cases included. Script authors relied on those details, even when they were not intended.
What changed the picture was POSIX.2 (IEEE Std 1003.2-1992), approved by the IEEE committee on 17 September 1992 (IEEE). It defines a shell language and a set of utilities, takes the System V Bourne shell as its base, and keeps together the code already written for the Bourne-derived variants. For the first time there was a written reference a rewrite could claim conformance to, rather than merely imitating a binary.
Bash’s relationship to POSIX.2 is stated openly: it implements the standard and adds extensions on top. POSIX mode, enabled with the --posix option or by setting the POSIXLY_CORRECT variable, realigns to the standard a set of behaviours that Bash handles its own way by default. That this mode has to exist already states the problem: Bash has to serve two masters, conformance to the standard and everyday interactive usefulness, and the two goals do not always agree.
Extensions and portability
The features Bash 2.x adds to the Bourne shell are the ones that make real scripting convenient: one-dimensional arrays, arithmetic expansion with $(( )), extended pattern matching, process substitution <(command) which presents a command’s output as though it were a file, command-line editing through the readline library. None of these is part of POSIX.2.
Hence the concrete decision every script author faces. A script using arrays and process substitution runs on Bash and breaks on a minimal POSIX shell, like the one many systems install as /bin/sh. A script that stays inside the POSIX subset runs everywhere, but gives up constructs that would make the code shorter and harder to get wrong.
The most treacherous case is the #!/bin/sh line. On many GNU/Linux distributions /bin/sh is a symbolic link to Bash, and Bash called as sh enters POSIX mode on its own. A script with a #!/bin/sh shebang that runs fine on its author’s machine can thus use Bash extensions without noticing, then break on a system where /bin/sh points to a different shell. The fault is not in the code: it is the gap between the interpreter you think you are calling and the one you actually call. The rule that follows is to declare the dependency honestly: #!/bin/bash when using the extensions, #!/bin/sh only when the body of the script stays within POSIX.2.
Implications
The distinction between standard and extension is not a textbook detail for anyone administering systems. It decides which machines run a given script untouched. A backup, log-rotation or provisioning script written against POSIX.2 survives a change of default shell, a move to a non-Linux system, or execution inside a minimal environment where Bash is absent.
There is also a consequence that touches the tool’s free nature. Bash is distributed under the GNU General Public Licence: the source is available, the behaviour is inspectable, the deviations from the standard are written down in the manual and in the CHANGES file. When a script behaves oddly, the cause is verified by reading the code or the documentation, not inferred by trial and error against an opaque binary. Where there was an observable but undocumented behaviour, the free rewrite put a documented and modifiable one in its place.
Limits
The reference standard is in motion. On 30 January 2002 the Austin Group — the joint working group of IEEE, ISO/IEC JTC 1 and The Open Group — published the combined revision known as IEEE Std 1003.1-2001 and Single UNIX Specification version 3 (The Open Group), which gathers into a single text the previously separate parts of POSIX. Bash 2.05a predates this publication by a few weeks: its conformance is measured against POSIX.2 of 1992, and alignment with the new text will take time. Writing “POSIX scripts” in 2002 therefore forces you to state which edition of the standard, because two now exist and the details diverge.
It also remains true that portability has a cost. The POSIX subset is more verbose and less expressive than full Bash, and the choice to give up the extensions has to be justified case by case. For a script that will run only on machines under one’s own control, where /bin/bash is guaranteed, strict adherence to the standard is wasted effort. The rule is not to push portability to the maximum in the abstract, but to know which level is needed and to declare it in the code.
https://www.gnu.org/software/bash/ https://lists.gnu.org/archive/html/info-gnu/2001-11/msg00004.html http://tiswww.case.edu/php/chet/bash/article.pdf https://standards.ieee.org/ieee/1003.2/1408/ https://pubs.opengroup.org/onlinepubs/009695399/ https://www.noze.it/en/insights/bash-open-source/
Cover image: Brian Fox, the author of Bash, in a half-length portrait: a bearded man with glasses — photo by Lissa Liggett, CC BY 3.0 — https://commons.wikimedia.org/wiki/File:BrianJFox.png