Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Bash & the POSIX Shell  Module 1 – Start here: the shell, the terminal and your first script

Shells, terminals and which Bash you have

How a terminal, a shell and the programs it runs differ, how to tell which shell and Bash version is running, and how to get Bash 5.3 on any system.

  • Beginner
  • 5 minutes
  • Examples run with Bash 5.3.20, dash 0.5.13.5, shellcheck 0.11.0 and Python 3.14.8
  • By MySmartCoPilot
Free lesson, Pro answers: 5 minutes
Free: the whole lesson. With a pass: the model answers to its 2 interview questions.

What you will learn

  • Explain the difference between a terminal emulator, a shell and the programs the shell runs
  • Identify the running shell and its version with $0, $BASH_VERSION and bash --version
  • Set up Bash 5.3 on Linux, macOS (Homebrew) or Windows (WSL or Git Bash)
What you’ll learn

What you will learn

  • Explain the difference between a terminal emulator, a shell and the programs the shell runs
  • Identify the running shell and its version with $0, $BASH_VERSION and bash --version
  • Set up Bash 5.3 on Linux, macOS (Homebrew) or Windows (WSL or Git Bash)
On this page

A brand-new Mac answers bash --version with version 3.2.57, while the current Bash is 5.3, and a script that uses a feature newer than that old copy stops with an error the moment it runs there. Before you write a single script, it pays to know what is drawing the text on your screen, which shell reads your commands and which version it is.

Below you will step through what happens when you press Enter, run one file under three different shells and compare what each reports, ask Bash for its version four ways, write a three-line guard that stops an old Bash politely, and set up Bash 5.3 on Linux, macOS or Windows.

A terminal draws text; the shell reads and runs your commands

When you type ls -l and press Enter, three different programs take part. The terminal emulator: The program that shows a text window, draws the characters programs write and passes your keystrokes on, such as Terminal on macOS or Windows Terminal. It runs no commands itself., such as Terminal on macOS or Windows Terminal, only draws characters and passes on your keystrokes. The shell: The program that reads command lines, expands them and starts the programs they name, then waits for them to finish. Bash, dash and zsh are shells., here Bash, reads the line, splits it into words, finds the program called ls and starts it. The program does the actual work and writes its output back to the terminal. Step through the six moments of that one command:

Interactive · message by message One command, from your keyboard to the screen Step through what the terminal, the shell and the program each do when you type ls -l and press Enter.
One command, from your keyboard to the screen, step 6 of 6. Messages so far: Terminal to Bash: ls -l, then Enter; Bash to ls: start ls with -l; ls to Terminal: the listing; ls to Bash: exit status 0; Bash to Terminal: the next prompt.Terminaldraws textBashreads commandslsa programls -l, then Enterstart ls with -lthe listingexit status 0the next prompt

The drawing shows the whole scene; its 6 steps are listed below.

Every step as text
  1. You type and press Enter. The terminal shows each key you press and sends the characters to the shell. It does not know what ls means; it only draws text and passes on keystrokes.
  2. The shell reads the line. Bash reads the whole line, splits it into the words ls and -l, and applies its expansions. The first word is the name of the command to run.
  3. The shell starts a program. Bash finds ls in one of the folders listed in PATH and starts it, handing it the word -l as its argument. Bash then waits for it to finish.
  4. The program writes the output. The ls program does the actual work. It reads the folder and writes the listing straight to the terminal, which draws it.
  5. The program exits. When ls finishes it ends with an exit status, 0 for success. Bash stores it in the special parameter $? so the next command can test it.
  6. The shell is ready again. Bash prints its prompt and waits for the next line. The terminal never ran a command; the shell started a program and the program did the work.

The terminal never ran anything: it only displayed what the shell and ls produced. That is why you can run Bash in any terminal app, and why changing the terminal’s colours or font changes nothing about how your commands behave.

Calling the terminal window Bash

Wrong: “I installed a new terminal, so now I have a new Bash”. Right: the terminal and the shell are separate programs. A new terminal app still starts whatever shell your account uses, and a new Bash works in your old terminal.

Bash, dash and zsh are different shells, and a script needs the right one

Several shells exist, and they share a common core. POSIX.1-2024, published by The Open Group and the IEEE as Issue 8 of their Base Specifications, defines a standard command interpreter, the sh language. Bash implements that language and adds much more, such as arrays and the [[ ]] test. The man page of dash, a small shell, calls it a command interpreter that takes in only the features POSIX designates, plus a few Berkeley extensions. And zsh is another large shell; Apple’s support page says that from macOS 10.15 a Mac uses zsh as its default login and interactive shell.

Shell Where you meet it Its part in this track
Bash 5.3 Linux systems, Homebrew on macOS, WSL and Git Bash on Windows The language every lesson teaches
dash A small shell that keeps to the POSIX features The check that a script is plain POSIX sh
zsh The default login and interactive shell of macOS from 10.15 Where many Mac users type, though scripts name bash

The file below prints what the shell running it says about itself. The same file is then run by GNU Bash 5.3.20, by macOS’s own /bin/bash and by dash:

which-shell.sh: which shell is this? Shell · which-shell.sh
#!/usr/bin/env bash
# Which shell is running this file, and which version is it?
echo "name:    $0"
echo "version: ${BASH_VERSION:-not Bash}"
echo "major:   ${BASH_VERSINFO:-none}"
One file, three shells Python · which_shell_session.py
from session import files, run

# The same file, run by three shells: GNU Bash 5.3.20, macOS's own /bin/bash and dash.
files("which-shell.sh")
run("""
bash which-shell.sh
/bin/bash which-shell.sh
dash which-shell.sh
""")

Output

$ bash which-shell.sh
name:    which-shell.sh
version: 5.3.20(1)-release
major:   5
$ /bin/bash which-shell.sh
name:    which-shell.sh
version: 3.2.57(1)-release
major:   3
$ dash which-shell.sh
name:    which-shell.sh
version: not Bash
major:   none

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 which_shell_session.py

Bash 5.3.20 reports major version 5 and macOS’s copy reports 3. Dash leaves BASH_VERSION empty, so the file prints the fallback after :- instead. A script written for Bash 5 may therefore work in the first shell, fail in the second and fail differently in the third, which is why a script states the shell it needs in its first line, the subject of this module’s last lesson.

Checkpoint

Check: Terminal, shell and program · Bash, dash, zsh and POSIX sh

  1. Question 1 of 2 You type ls -l in a terminal window and press Enter. Which program finds ls and starts it?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: The shell, Bash

    Three programs take part: the terminal draws and passes on keys, the shell reads the line and starts ls, and ls does the work and writes the listing, which the terminal draws.

  2. Question 2 of 2 Run by dash, which-shell.sh printed "version: not Bash". Why?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Dash does not set BASH_VERSION, so the fallback after :- was printed

    ${NAME:-word} prints word when NAME is unset or empty. Bash sets BASH_VERSION and BASH_VERSINFO; dash sets neither, so both fallbacks appear.

Four checks tell you which Bash is running

You can ask a running Bash about itself in several ways. $0 holds the name the shell was started with, $BASH_VERSION the full version, and the array BASH_VERSINFO its parts, so ${BASH_VERSINFO[0]} is the major version. bash --version asks the first bash on your PATH, and type -a bash lists every bash the shell can find, in the order it would use them. Here they are, typed into an interactive Bash 5.3.20:

Asking Bash which version it is Python · find_bash_session.py
from session import run

# Four ways to ask which Bash you have, typed into an interactive Bash 5.3.20.
run("""
echo "$0"
echo "$BASH_VERSION"
echo "${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}"
bash --version | head -n 1
type -a bash
echo "$SHELL"
""")

Output

$ echo "$0"
bash
$ echo "$BASH_VERSION"
5.3.20(1)-release
$ echo "${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}"
5.3
$ bash --version | head -n 1
GNU bash, version 5.3.20(1)-release (aarch64-apple-darwin25.6.0)
$ type -a bash
bash is …/bash
bash is /bin/bash
$ echo "$SHELL"
/bin/zsh

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 find_bash_session.py

Two lines need care. type -a bash found two copies: the 5.3.20 build first and macOS’s /bin/bash second, so typing bash runs the first. And $SHELL printed /bin/zsh, because SHELL holds your login shell: The shell your account starts when you log in, recorded in the SHELL variable. It need not be the shell that is running a given script., the one your account starts, not the shell that is running now; on this Mac that is zsh, although Bash ran every line.

A script can check the version itself and stop before it fails halfway. This guard needs Bash 4 or later:

version-gate.sh: stop on an old Bash Shell · version-gate.sh
#!/usr/bin/env bash
# Stop at once, with a clear message, when an older Bash runs this script.
if [ -z "${BASH_VERSINFO:-}" ] || [ "${BASH_VERSINFO[0]}" -lt 4 ]; then
  echo "This script needs Bash 4 or later; this is ${BASH_VERSION:-not Bash}." >&2
  exit 1
fi
echo "Bash ${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}: new enough"
The guard on Bash 5.3.20 and on Bash 3.2.57 Python · version_gate_session.py
from session import files, run

# The guard passes on Bash 5.3.20 and stops macOS's Bash 3.2.57 and dash with a clear message.
files("version-gate.sh")
run("""
bash version-gate.sh
!/bin/bash version-gate.sh
!dash version-gate.sh
shellcheck version-gate.sh
""")

Output

$ bash version-gate.sh
Bash 5.3: new enough
$ /bin/bash version-gate.sh
This script needs Bash 4 or later; this is 3.2.57(1)-release.
[exit status 1]
$ dash version-gate.sh
This script needs Bash 4 or later; this is not Bash.
[exit status 1]
$ shellcheck version-gate.sh

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 version_gate_session.py

On Bash 5.3.20 it prints “Bash 5.3: new enough”; on macOS’s Bash 3.2.57 and on dash it prints its message to standard error and ends with exit status 1 before any later line can misbehave. Under dash the first test already succeeds, so the || never reaches the array syntax that dash cannot read. ShellCheck 0.11.0 printed nothing about the file, which means it found no problem.

Key idea

Trust what the running shell says about itself: $BASH_VERSION and BASH_VERSINFO describe the shell that runs the script, while $SHELL only names your login shell.

A current Bash is one install away on Linux, macOS and Windows

How you get Bash 5.3 depends on the system. Most Linux distributions include Bash and update it through their package manager, though each release ships its own version, so check with bash --version rather than assuming. On macOS, /bin/bash stays at 3.2.57; Homebrew’s bash formula is 5.3.20, and Homebrew installs to /opt/homebrew on Apple silicon. On Windows, Microsoft’s Windows Subsystem for Linux gives you a full Linux, Bash included, after one wsl --install command in an administrator PowerShell, while Git for Windows includes Git Bash, a Bash emulation built for running Git from the command line.

System How to get Bash 5.3 How to check
Linux The distribution’s package manager bash --version
macOS brew install bash, then use /opt/homebrew/bin/bash type -a bash lists it before /bin/bash
Windows WSL with a Linux distribution, or Git Bash bash --version inside WSL or Git Bash

Test with the Bash your readers will use

Run every script you share with the newest Bash you can and with the oldest one your users might have. On a Mac, that means testing with Homebrew’s Bash and, for anything that must also run there, macOS’s /bin/bash.

Every session in this track was recorded with GNU Bash 5.3.20, built from the official bash-5.3 sources with the patches bash53-001 to bash53-020, so your output will match when your version line says 5.3.20 too.

Checkpoint

Check: Finding the running Bash · Getting Bash 5.3

  1. Question 1 of 2 You are typing into Bash 5.3.20, yet echo "$SHELL" prints /bin/zsh. What does that tell you?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: zsh is your login shell; the shell running now is Bash, as $BASH_VERSION shows

    To learn which shell runs your commands, ask the shell itself with $0, $BASH_VERSION or BASH_VERSINFO. SHELL only names your login shell, zsh on a new Mac.

  2. Question 2 of 2 On a Mac with Apple silicon you run brew install bash. Where is the new Bash, and how do you check that typing bash runs it?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: In /opt/homebrew/bin; type -a bash should list it before /bin/bash

    Two copies then exist. type -a bash shows every bash in PATH order, and bash --version shows which one answers when you type bash.

Practise: name the shell from its output

Each question shows output a shell printed or a situation from a real setup. Decide which shell or version produced it; every wrong answer says what it confuses:

Practice that adapts to you

Practise this lesson

8 questions about 4 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 8 You switch from one terminal app to another with a different font and colours. What changes about how your commands run?

    Choose one answer.

    Show the answer: Question 1 of 8

    Answer: Nothing; the same shell runs them and only the drawing of the text changes

    Terminals are interchangeable. The shell reads and runs the commands, and the programs produce the output the terminal draws.

  2. Question 2 of 8 A job runs a backup script every night while nobody is logged in and no window is open. Does the script need a terminal?

    Choose one answer.

    Show the answer: Question 2 of 8

    Answer: No; a shell reads and runs the script, and a terminal is only needed to show text to a person

    The terminal and the shell are separate programs. Scheduled jobs, build servers and containers run shell scripts every day with no terminal attached.

  3. Question 3 of 8 What does POSIX.1-2024 define that both Bash and dash implement?

    Choose one answer.

    Show the answer: Question 3 of 8

    Answer: The sh command language, a standard command interpreter

    POSIX.1-2024 (Issue 8 of The Open Group's Base Specifications) defines the sh language. Scripts that keep to it run in Bash and dash alike.

  4. Question 4 of 8 A script that uses Bash arrays begins with a line telling the system to run it with sh, and on this system sh is dash. What happens when the array line runs?

    Choose one answer.

    Show the answer: Question 4 of 8

    Answer: Dash stops with a syntax error, because POSIX sh has no arrays

    A script must run under the shell it was written for. Bash features such as arrays and [[ ]] fail in dash; name bash in the first line, or keep to POSIX sh.

  5. Question 5 of 8 Which shell answered bash --version with the line "GNU bash, version 3.2.57(1)-release"?

    Choose one answer.

    Show the answer: Question 5 of 8

    Answer: macOS's own /bin/bash

    The version line names the copy that ran. On a Mac, 3.2.57 means /bin/bash ran, usually because Homebrew's Bash is not first in PATH.

  6. Question 6 of 8 The lesson's version-gate.sh runs under /bin/bash 3.2.57. With what exit status does it end?

    Type a number.

    Show the answer: Question 6 of 8

    Answer: 1 exit status

    BASH_VERSINFO[0] is 3, which is less than 4, so the guard prints its message to standard error and runs exit 1, as the recorded session shows.

  7. Question 7 of 8 Which command, typed into an administrator PowerShell, installs the Windows Subsystem for Linux?

    Choose one answer.

    Show the answer: Question 7 of 8

    Answer: wsl --install

    wsl --install sets up WSL with a Linux distribution, which brings its own Bash. Git for Windows is the other way to get Bash on Windows.

  8. Question 8 of 8 A Windows user needs Bash only to run Git commands, while a colleague must run Linux build scripts. What fits each?

    Choose one answer.

    Show the answer: Question 8 of 8

    Answer: Git Bash for the first, WSL for the second

    Match the tool to the job: Git Bash for Git from the command line, WSL for scripts that expect a Linux system.

Interview questions

Warm-up (fresher to 2–5 years): how does a terminal differ from a shell?

A terminal, today usually a terminal emulator such as Terminal on macOS or Windows Terminal, is the window that draws text and sends your keystrokes on. A shell such as Bash, zsh or dash is the program inside it that reads each command line, expands it and starts the programs it names, then waits for them to finish. The two are independent: you can run any shell in any terminal, and a script runs under a shell with no terminal at all, as cron jobs do. To see which shell you are in, run echo "$0"; to see its version in Bash, run echo "$BASH_VERSION". $SHELL names your login shell, which may differ from the one you are using.

Two more questions about versions and portability follow. Answer each one before you open its first step:

Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.

  1. Fresher to mid

    A script that works on your Linux laptop stops on a colleague's Mac with "declare: -A: invalid option". What is going on, and how do you fix it for both of you?

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  2. Mid to senior

    How would you make a Bash script stop at once, with a clear message, when someone runs it with sh or with a Bash older than version 4?

    Model answer, Pro. First step and follow-ups

Flashcards · 5 cards

Recall it, then check

Say the answer to yourself before you look: recalling it is what makes it stick.

  1. What is the difference between a terminal emulator and a shell?

    The terminal emulator is the window: it draws characters and sends your keystrokes on, and runs no command itself. The shell, such as Bash, zsh or dash, is the program inside it that reads each command line, expands it and starts the programs it names.

  2. Why does echo $SHELL not tell you which shell is running a script?

    SHELL names your login shell, the one your account starts when you log in. A script can run under a different shell, so ask the running shell itself through BASH_VERSION or BASH_VERSINFO.

  3. Which checks tell you which Bash you are running, and which version it is?

    In an interactive shell $0 gives the name the shell was started with. BASH_VERSION and the BASH_VERSINFO array describe the running shell, bash --version reports the bash found first on PATH, and type -a bash lists every bash on PATH in search order.

  4. Which Bash does macOS keep at /bin/bash, and how do you get a current one?

    Bash 3.2.57. Install Bash 5.3 with Homebrew on macOS, with the package manager on Linux, or through WSL or Git Bash on Windows, and then read its version line.

  5. Which document defines the sh language, and how do Bash, dash and zsh relate to it?

    POSIX.1-2024 defines it. dash implements it closely, Bash implements it and adds many extensions, and zsh, the default login shell of macOS from 10.15, is a separate shell with its own language.

Key takeaways

  • A terminal emulator draws text and passes on keystrokes, the shell reads and expands command lines and starts programs, and the programs do the work.
  • POSIX.1-2024 defines the sh language; Bash and dash implement it, Bash adds much more, and zsh is the default login shell on macOS from 10.15.
  • $0, $BASH_VERSION, BASH_VERSINFO, bash --version and type -a bash tell you which Bash is running, while $SHELL names only your login shell.
  • macOS keeps Bash 3.2.57 at /bin/bash, so install Bash 5.3 with Homebrew, your Linux package manager, WSL or Git Bash, and check the version line.

Terms in this lesson

login shell
The shell your account starts when you log in, recorded in the SHELL variable. It need not be the shell that is running a given script.
shell
The program that reads command lines, expands them and starts the programs they name, then waits for them to finish. Bash, dash and zsh are shells.
terminal emulator
The program that shows a text window, draws the characters programs write and passes your keystrokes on, such as Terminal on macOS or Windows Terminal. It runs no commands itself.

References

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.