Modern macOS uses Zsh as its default login shell, but it still includes Bash 3.2
at /bin/bash. If a script needs Bash 4 or newer, install the current Bash with
Homebrew instead of changing the system copy.
At the time of writing, Bash 5.3 is the current major release and Homebrew provides the latest 5.3.x version. The Bash 4 notes from the original 2015 article are preserved below.
Check which Bash you are using
These commands answer slightly different questions:
/bin/bash --version
bash --version
command -v bash
printf '%s\n' "$BASH_VERSION"/bin/bash --versionchecks the Bash supplied by macOSbash --versionchecks the firstbashfound in yourPATHcommand -v bashprints the path to that executable$BASH_VERSIONreports the version of the Bash process currently running
On macOS, /bin/bash --version will commonly report a version such as
3.2.57(1)-release. Installing another Bash does not and should not replace
that file.
Install Bash 5.3 with Homebrew
First, install Homebrew if you do not already have it. Then install Bash:
brew install bashIf you already installed Bash 4 or 5 with Homebrew, upgrade it instead:
brew update
brew upgrade bashVerify the Homebrew executable directly:
brew_bash="$(brew --prefix)/bin/bash"
"$brew_bash" --versionUsing brew --prefix avoids hard-coding the installation path. Homebrew uses
/opt/homebrew on Apple Silicon and /usr/local on Intel Macs.
Homebrew normally adds its bin directory to your PATH. If command -v bash
still prints /bin/bash, follow the shell setup instructions printed by the
Homebrew installer. For the current terminal session, you can run:
eval "$(brew shellenv)"
command -v bashChoose the Bash used by scripts
A script with this shebang always uses the macOS system Bash:
#!/bin/bash
printf '%s\n' "$BASH_VERSION"For a script that requires Bash 4 or newer and should work across macOS and
Linux, use env:
#!/usr/bin/env bash
printf '%s\n' "$BASH_VERSION"env selects the first bash in the script's PATH, so check that Homebrew's
bin directory comes before /bin. A direct shebang such as
#!/opt/homebrew/bin/bash is more predictable on one machine but will not work
on Intel Macs or most Linux systems.
Make the script executable and run it directly so the shebang takes effect:
chmod +x version-test.sh
./version-test.shDo not run a Bash-specific script with sh version-test.sh. That explicitly
uses sh and ignores the script's Bash shebang.
Make Homebrew Bash your login shell
This step is optional. You do not need to change your login shell merely to run Bash scripts.
Add the Homebrew Bash path to the allowed login shells, without adding it a second time, and then select it:
brew_bash="$(brew --prefix)/bin/bash"
if ! grep -qxF "$brew_bash" /etc/shells; then
printf '%s\n' "$brew_bash" | sudo tee -a /etc/shells
fi
chsh -s "$brew_bash"Close and reopen the terminal, then verify both the configured login shell and the running process:
printf '%s\n' "$SHELL"
ps -p $$ -o command=
printf '%s\n' "$BASH_VERSION"If you prefer Zsh for interactive use, leave it as the default. Modern macOS uses Zsh by default, and installing Bash does not change that.
The original Bash 4 upgrade
When this article was first published in 2015, Homebrew's brew install bash
installed Bash 4. The important distinction was between Apple's /bin/bash 3.2
and Homebrew's newer executable.
On the Intel Macs of the time, Homebrew installed Bash here:
/usr/local/bin/bash --versionA script using #!/bin/bash still ran Bash 3.2, while changing its shebang to
the following ran the Homebrew Bash 4 installation:
#!/usr/local/bin/bashThe more portable recommendation was, and still is:
#!/usr/bin/env bashThat historical /usr/local/bin/bash path remains correct for a standard
Homebrew installation on an Intel Mac. Apple Silicon uses
/opt/homebrew/bin/bash, which is why the modern instructions above discover
the prefix instead of assuming one.
Why Bash 4 still matters
Bash 4.0 introduced associative arrays, recursive ** globbing, coprocesses,
case-changing parameter expansions, and other improvements. Associative arrays
are a common reason that a script works in modern Bash but fails under the
macOS-provided Bash 3.2. See
how associative arrays work in Bash for examples:
declare -A user_roles=(
[alice]=admin
[bob]=editor
)
printf '%s\n' "${user_roles[alice]}"Bash 5.3 includes those Bash 4 features along with the changes and fixes from the Bash 5 releases. Unless you are reproducing an old environment, install the current release rather than pinning a new setup to Bash 4.
Leave the system shells alone
Do not replace /bin/bash or /bin/sh. macOS owns those paths, and scripts may
depend on their system-provided behavior. Installing Bash with Homebrew gives
you a separate executable and leaves the operating system copies intact.
To see the shells allowed as login shells, run:
cat /etc/shells