The Bourne Shell (binary command name sh) is the historic, foundational command-line interpreter and script execution environment designed for the Unix operating system. Developed by computer scientist Stephen Bourne at AT&T Bell Laboratories in Murray Hill, New Jersey, it was officially released in 1979 with Version 7 Unix (V7).
Before the Bourne Shell, early Unix systems used Ken Thompson's rudimentary "Thompson Shell" (1971), which had no programmatic control flow (loops or conditionals) and required external utility calls for almost every logical operation. Stephen Bourne revolutionized systems programming by creating a shell that was simultaneously a responsive interactive command interpreter and a full-fledged, structured, algorithmic scripting language.
In Linux architecture, the Kernel sits at the core managing CPU scheduling, RAM allocation, hardware drivers, and raw filesystem access. The user never communicates directly with the kernel; instead, the Shell acts as an outer protective layer (hence the name "shell") wrapping around the kernel:
| Operating Mode | Description & Behavior |
|---|---|
| Interactive Mode | The shell reads commands entered directly by the human user at the command line prompt ($ for standard users, # for root), parses arguments, forks child processes to execute them, and displays results to standard output. |
| Non-Interactive (Batch) Mode | The shell reads a file containing a sequential list of commands (a shell script) and executes them line-by-line automatically, providing exit status codes ($?) upon completion. |
Stephen Bourne introduced syntax rules that became the universal standard codified in the POSIX (Portable Operating System Interface) specification:
| Feature Concept | Syntax / Notation | Architectural Purpose |
|---|---|---|
| Environment Variables | export VAR="val" |
Allows variables defined in the current shell process to be inherited by all child processes executed from it (e.g., $PATH, $USER). |
| I/O Redirection | >, >>, <, 2> |
Redirecting standard output to overwrite (>) or append (>>) files, reading standard input (<), and isolating standard error streams (2>). |
| UNIX Pipelines | cmd1 | cmd2 |
Pipes the standard output of cmd1 directly into the standard input of cmd2 without intermediate temporary disk files. |
| Command Substitution | `date` or $(date) |
Executes a sub-command and replaces the command string with its evaluated standard output text. |
| Control Flow Blocks | if...fi, case...esac |
Structured branching constructs borrowed from Algol 68. Notice the closing keywords are mirror reversals of the opening tags! |
| Signal Trapping | trap 'clean_up' EXIT |
Enables catching system signals (such as Ctrl+C SIGINT or script exit) to clean up temporary files cleanly. |
/bin/sh vs. Bash & Dash On modern Linux computers, the original proprietary Bell Labs Bourne Shell is rarely installed. Instead, /bin/sh is a standardized symbolic link pointing to a modern, open-source POSIX-compliant implementation:
/bin/sh points to Dash (Debian Almquist Shell). Dash is a tiny, blazing-fast POSIX shell (~150 KB) that boots the operating system and runs system scripts with minimal RAM and CPU overhead./bin/sh points directly to Bash (GNU Bourne Again Shell). When invoked as sh, Bash automatically turns on its strict POSIX-compliance compatibility mode.#!/bin/sh, you must avoid Bash-only syntax such as double brackets [[ $a == $b ]], indexed arrays, or the source keyword. Strict POSIX compliance uses single brackets [ "$a" = "$b" ] and the dot operator . ./file.sh.
Let us create, inspect, and execute a 100% portable Bourne shell script:
/bin/sh# Check where /bin/sh points on your system:
ls -l /bin/sh
# On Ubuntu/Debian: /bin/sh -> dash
# On Fedora/RHEL: /bin/sh -> bash
# Check your current login shell:
echo $SHELL
Create a file named backup_check.sh using your text editor:
#!/bin/sh
# Portable Bourne / POSIX Shell Script
# 1. Variables (No spaces around '=')
BACKUP_DIR="/tmp/student_backup"
TARGET_FILE="/etc/hosts"
# 2. Conditionals using standard test '[' operator
if [ ! -d "$BACKUP_DIR" ]; then
echo "Creating backup directory: $BACKUP_DIR"
mkdir -p "$BACKUP_DIR"
fi
# 3. Copying and logging
echo "Backing up $TARGET_FILE..."
cp "$TARGET_FILE" "$BACKUP_DIR/"
# 4. Check Exit Status ($?)
if [ $? -eq 0 ]; then
echo "Backup completed successfully!"
ls -l "$BACKUP_DIR"
else
echo "Error: Backup failed!" 1>&2
exit 1
fi
# Grant execute permissions:
chmod +x backup_check.sh
# Run the script normally:
./backup_check.sh
# Run the script in trace debugging mode (prints each command executed):
sh -x ./backup_check.sh
| Special Variable | Description |
|---|---|
$0 |
The name of the script itself as invoked. |
$1 – $9 |
The 1st through 9th command-line arguments passed to the script. |
$# |
The total count of command-line arguments passed. |
$* |
All arguments as a single concatenated string: "$1 $2 $3". |
$@ |
All arguments individually quoted: "$1" "$2" "$3" (safest for loop iteration). |
$? |
Exit status of the most recently executed command (0 = success, non-zero = failure). |
$$ |
The Process ID (PID) of the currently running shell script. |
sh and is located at /bin/sh. In modern Linux distributions, /bin/sh is typically a symbolic link pointing to a lightweight POSIX-compliant shell like Dash (on Debian/Ubuntu) or Bash (in POSIX compatibility mode on RHEL/Fedora).
export), structured algorithmic control flow (if/then/else/fi, for/in/do/done, while/do/done, case/esac), input/output file redirection (<, >, >>), standard error separation (2>), here documents (<<), subshell grouping with parentheses, and signal trap handling.
/bin/sh (without Bashisms) guarantees 100% portability across all Unix-like operating systems—including Linux distributions, FreeBSD, OpenBSD, macOS, Solaris, and lightweight embedded Alpine Linux containers that lack full Bash.
$), while for the root administrative user, the prompt switches to the hash sign (#).
The Bourne Shell established the syntax and execution model upon which modern cloud automation and DevOps scripts rely. In the next tutorial, we examine the shell created for C programmers at UC Berkeley: Class 26: The C Shell (csh / tcsh).