Skip to content

Instantly share code, notes, and snippets.

Created February 7, 2012 11:52
Show Gist options
  • Star 90 You must be signed in to star a gist
  • Fork 20 You must be signed in to fork a gist
  • Save samnang/1759336 to your computer and use it in GitHub Desktop.
Save samnang/1759336 to your computer and use it in GitHub Desktop.
Install Bash version 4 on MacOS X
# Install Bash 4 using homebrew
brew install bash
# Or build it from source...
curl -O
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 (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
Copy link

srohatgi commented Jun 3, 2014

./configure --prefix=/usr/local

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

Copy link

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'

Copy link

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'
   echo '/usr/local/bin/bash seems to exist already in your shell options'

Copy link

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

Copy link

More idiomatically:

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

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

Copy link

aleclarson commented Feb 26, 2018

Not working for me:

$ echo $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 <>

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


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

Copy link

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)

# initial setup
cd ~/
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"
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"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment