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

srohatgi 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

derhuerst 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

aaronmehar 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

cfs-pure 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

willbuckner 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

aleclarson 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

arthurdapaz 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.