Upgrade Bash on macOS from 3.2 or 4 to 5.3

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 --version checks the Bash supplied by macOS
  • bash --version checks the first bash found in your PATH
  • command -v bash prints the path to that executable
  • $BASH_VERSION reports 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 bash

If you already installed Bash 4 or 5 with Homebrew, upgrade it instead:

brew update
brew upgrade bash

Verify the Homebrew executable directly:

brew_bash="$(brew --prefix)/bin/bash"
"$brew_bash" --version

Using 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 bash

Choose 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.sh

Do 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 --version

A 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/bash

The more portable recommendation was, and still is:

#!/usr/bin/env bash

That 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

Further reading