C.W.K.
Stream
Lesson 02 of 10 · published

A Brief History: sh → bash → zsh → fish

~15 min · history, sh, bash, zsh, fish, posix

Level 0Window Tourist
0 XP0/95 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

Why care about the shell timeline?

You will read scripts written for sh in 1989 alongside zsh config files written last week. Knowing which shell each tool targets keeps you from copying a piece of bash-only syntax into a strict POSIX script and watching it explode in CI.

1979 — Bourne shell (sh)

Stephen Bourne wrote sh at Bell Labs to replace the original Thompson shell. It defined the syntax that everyone else cloned: pipes, if/then/fi, here-docs, environment variables, $?. When you write #!/bin/sh, you are asking for that minimal Bourne-flavored grammar — no arrays, no [[ ]], no fancy expansion.

1989 — Bourne Again (bash)

bash is the GNU project's free Bourne replacement. It absorbed ideas from Korn shell (ksh) and C shell (csh): history, command-line editing, arrays, [[ ]] conditionals, $(...) substitution. macOS used bash as the default from 10.3 (2003) until 10.15 (2019), but Apple froze the version at 3.2 because later releases switched to GPLv3.

1990 — Z shell (zsh)

Paul Falstad wrote zsh to be "bash plus everything good from the others." Better completion, recursive globbing (**), prompt themes, named directories, modular plugins via Oh-My-Zsh / Prezto / zinit. macOS Catalina (2019) made it the default login shell.

2005 — fish

fish ("friendly interactive shell") rejected POSIX compatibility on purpose. It has the smartest defaults of any shell — autosuggestions, syntax highlighting, sane scripting — but you cannot run a bash script verbatim. fish is for the prompt, not for portable scripts.

The rule of thumb

Use zsh (or fish) for your interactive prompt. Use bash or POSIX sh for scripts you ship to other machines. Never assume a script's interpreter — always set the shebang.

Code

What's installed on this Mac?·bash
# All registered login shells
cat /etc/shells
# Where each one lives
for s in sh bash zsh fish; do
  printf '%-5s -> ' "$s"
  command -v "$s" || echo '(not installed)'
done
Pin the interpreter so the script doesn't surprise you·bash
#!/usr/bin/env bash
# Use bash specifically, not whatever sh happens to be linked to
set -euo pipefail
echo "running on $(bash --version | head -1)"

External links

Exercise

Run cat /etc/shells on your Mac. Then command -v bash and bash --version. Confirm bash is 3.2.x. If you want a modern bash, brew install bash and check the new path with command -v bash again — Homebrew puts it under /opt/homebrew/bin/bash while system bash is /bin/bash.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.