# 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](https://lists.gnu.org/archive/html/bug-bash/2025-07/msg00005.html) 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:

```shell
/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](https://brew.sh/) if you do not already have it. Then
install Bash:

```shell
brew install bash
```

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

```shell
brew update
brew upgrade bash
```

Verify the Homebrew executable directly:

```shell
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:

```shell
eval "$(brew shellenv)"
command -v bash
```

## Choose the Bash used by scripts

A script with this shebang always uses the macOS system Bash:

```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`:

```bash
#!/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:

```shell
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:

```shell
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:

```shell
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:

```shell
/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:

```bash
#!/usr/local/bin/bash
```

The more portable recommendation was, and still is:

```bash
#!/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](/associative-arrays-in-bash) for examples:

```bash
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:

```shell
cat /etc/shells
```

## Further reading

- [Bash 5.3 release announcement](https://lists.gnu.org/archive/html/bug-bash/2025-07/msg00005.html)
- [Bash 5.3 reference manual](https://www.gnu.org/software/bash/manual/)
- [Bash 4.0 release announcement](https://lists.gnu.org/archive/html/bug-bash/2009-02/msg00164.html)
- [Homebrew Bash formula](https://formulae.brew.sh/formula/bash)
- [Homebrew installation prefixes](https://docs.brew.sh/Installation)
- [Change the default shell in Terminal on Mac](https://support.apple.com/guide/terminal/trml113/mac)
