Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Install Bash version 4 on MacOS X
# Install Bash 4 using homebrew
brew install bash
# Or build it from source...
curl -O http://ftp.gnu.org/gnu/bash/bash-4.2.tar.gz
tar xzf bash-4.2.tar.gz
cd bash-4.2
./configure --prefix=/usr/local/bin && make && sudo make install
# Add the new shell to the list of legit shells
sudo bash -c "echo /usr/local/bin/bash >> /private/etc/shells"
# Change the shell for the user
chsh -s /usr/local/bin/bash
# Restart terminal.app (new window works too)
# Check for Bash 4 and /usr/local/bin/bash...
echo $BASH && echo $BASH_VERSION
# Put this somewhere in your dotfiles to turn on recursive globbing
shopt -s globstar
# Source your dotfiles...
source path/to/dotfiles
# Now you can double glob your way into distant directories
cd some/uportal/project/root
cd **/skins
@srohatgi

This comment has been minimized.

Copy link

commented Jun 3, 2014

./configure --prefix=/usr/local

worked for me, otherwise bash was installed in /usr/local/bin/bin/bash

@derhuerst

This comment has been minimized.

Copy link

commented May 21, 2015

I added a safety check if /usr/local/bin/bash is already present in /private/etc/shells:

if [ $(cat /private/etc/shells | grep '/usr/local/bin/bash' | wc -l) -eq 0 ]; then
    sudo bash -c 'echo /usr/local/bin/bash >> /private/etc/shells'
fi
@aaronmehar

This comment has been minimized.

Copy link

commented Jun 18, 2016

Avoiding the cats, and wc processing, you can shorten the check; but the check is a good idea.

if [ $(grep -c /private/etc/shells /usr/local/bin/bash) -eq 0 ]; then
    sudo bash -c 'echo /usr/local/bin/bash >> /private/etc/shells'
elif 
   echo '/usr/local/bin/bash seems to exist already in your shell options'
fi
@cfs-pure

This comment has been minimized.

Copy link

commented Jul 15, 2016

You can shorten the if even more by getting rid of test and the equality check by using the return code of grep:

if grep -q /usr/local/bin/bash /private/etc/shells; then

@willbuckner

This comment has been minimized.

Copy link

commented Nov 10, 2017

More idiomatically:

if ! grep -q /usr/local/bin/bash /private/etc/shells; then
    echo /usr/local/bin/bash | sudo tee -a /private/etc/shells
else
    echo '/usr/local/bin/bash already found in /private/etc/shells'
fi

Or as a concise one-liner:

grep -q /usr/local/bin/bash /private/etc/shells || echo /usr/local/bin/bash | sudo tee -a /private/etc/shells
@aleclarson

This comment has been minimized.

Copy link

commented Feb 26, 2018

Not working for me:

$ echo $BASH
/usr/local/bin/bash

$ $BASH --version
GNU bash, version 4.4.19(1)-release (x86_64-apple-darwin17.3.0)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

$ echo $BASH_VERSION
3.2.57(1)-release

$ bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
Copyright (C) 2007 Free Software Foundation, Inc.

Edit: In the Terminal preferences, change "Shells open with" to use /usr/local/bin/bash --login and the $BASH_VERSION will be correct when you open a new window or restart Terminal.

I think you need to alias bash="/usr/local/bin/bash" if you want the bash command to use Bash 4.

@arthurdapaz

This comment has been minimized.

Copy link

commented Apr 16, 2019

Ok! Just created a script that install latest bash on MacOS Mojave 10.14.*
It also creates a uninstall at ~/.bash/bash_uninstall (in case you want to revert changes back)
It takes care of everything and it's working like a charm. :)

Why I did this? Because I preffer to do things manually on my hackintosh...

#!/usr/bin/env bash

# Install Bash 5.0 (MacOS)
VERSION="5.0"
BASH_SHORT="bash-$VERSION"
BASH_SRC="$BASH_SHORT.tar.gz"
BASH_URL="https://ftp.gnu.org/gnu/bash"
BASH_PREFIX="/usr/local"
BASH_PATH="$BASH_PREFIX/bin/bash"

# initial setup
cd ~/
curl -Ok $BASH_URL/$BASH_SRC
tar -zxvf $BASH_SRC

mv $BASH_SHORT .bash && cd .bash/
./configure --prefix=$BASH_PREFIX && make && sudo make install

printf "\nInstalled bash'es:\n"
which -a bash

printf "\nWhitelisting the new bash...\n" 
grep -q $BASH_PATH /private/etc/shells || echo $BASH_PATH | sudo tee -a /private/etc/shells

printf "\nSetting default shell:\n" 
chsh -s $BASH_PATH
sudo chsh -s $BASH_PATH

printf "\nCreating uninstaller..."
touch bash_uninstall
cat > bash_uninstall <<EOF
#!/usr/bin/env bash
cd ~/.bash
sudo make uninstall clean
printf "\nCleaning whitelist...\n"
sed /$(sed 's:/:\\/:g' <<< $BASH_PATH)/d /private/etc/shells
printf "\nRemoving leftovers...\n"
rm -rf ~/.bash && cd ~/
printf "\nSetting old bash back...\n"
chsh -s /bin/bash
sudo chsh -s /bin/bash
printf "\nInstalled bash'es:\n"
which -a bash
printf "\nOld bash is back!\n"
EOF
chmod +x bash_uninstall

printf "\nCleaning source: "
cd ~/ && rm -vf $BASH_SRC

printf "\n\nExit terminal and reopen to start using $BASH_SHORT\nTo uninstall it and revert to old:\n~/.bash/bash_uninstall\n"
exit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.