When you run a shell within your login shell, $SHELL is still your login shell. When you run another shell within that shell, $SHELL still stays the same. There are some bad scripts the behavior of which incorrectly depends on $SHELL. If you want to run Bash, you might want $SHELL to stay /bin/bash.
And sometimes you want to login to a version of Bash not from /etc/shells — like, from somewhere else in the system or even from your home directory.
I'm not sure if there is any non-shell-specific standard way of getting the path of your childmost shell executable. In Bash you can get it from $BASH.
If you want to land in /bin/bash only if your own bash binary doesn't get found in $PATH, put this in your .bashrc:
(return $NO_FURTHER_PLEASE) && [[ $BASH == "/bin/bash" ]] && { NO_FURTHER_PLEASE=1 bash; exit $?; }
You might want to replace "/bin/bash" for $SHELL in the above if you are not sure if your login shell will stay /bin/bash since $SHELL will be always your login shell from /etc/shells.
If you also want to land in /bin/bash wherever it is already Bash 5 or newer, put this instead:
(return $NO_FURTHER_PLEASE) && [ "${BASH_VERSINFO:-0}" -le 4 ] && { NO_FURTHER_PLEASE=1 bash; exit $?; }
Note that in both cases if the bash from $PATH ends up being /bin/bash, you get /bin/bash inside /bin/bash. That could be improved on by re-checking against the original condition with something like
((return $NO_FURTHER_PLEASE) || [ the condition goes there ]) && (exit 2)
or instead, even better,
(return $NO_FURTHER_PLEASE) && [[ $SHELL == $BASH ]] && (exit 2)
Of course, one could just hardcode the absolute path of their bash in .bashrc and then there would be no such problem.
If someone is wondering, no, $NO_FURTHER_PLEASE is not inherited by any bash that you choose to run inside your bash since NO_FURTHER_PLEASE is not exported.
Yes yes i know that there is probably a neater way to test against a variable than returning it from a subshell, i am just too lazy to look for it.
Edit
It seems like all of the above could be replaced with just
FURTHER_BASH=$(type -p bash)
if [[ $SHELL != $BASH ]]
then
    unset FURTHER_BASH
elif [[ $BASH != $FURTHER_BASH ]]
then 
    $FURTHER_BASH
    exit $?
else
    unset FURTHER_BASH
    echo "Staying in login shell." >&2
fi
[ "${BASH_VERSINFO:-0}" -le 4 ] && {
    echo "Warning: Staying in bash version $BASH_VERSINFO < 5."
    (exit 2)
}
 

 
    
Top comments (0)