The test command [ -t 1 ]
checks whether bash's output is on a terminal. The intent of this line is clearly to run zsh when opening a terminal, without disrupting other uses of bash. But it's done very badly.
The file .bashrc
is read in three circumstances:
- When bash is executed as an interactive shell, i.e. to run commands typed by the user rather than to execute batch commands.
- When bash is a non-interactive shell which is run by an RSH or SSH daemon (typically because you run
ssh host.example.com somecommand
and bash is your login shell on host.example.com
).
- When it's invoked explicitly, e.g. in a user's
.bash_profile
(bash's choice of startup files is a bit weird).
[ -t 1 ]
is a poor way to detect interactive shells. It's possible, but rare, to run bash interactively with standard output not going to a terminal. It's more common to have standard output going to a terminal in a non-interactive shell; a non-interactive shell has no business running .bashrc
but unfortunately bash shells invoked by SSH do. There's a much better way: bash (and any other sh-style shell) provides a built-in, reliable method to do it.
case $- in
*i*) echo this shell is interactive;;
*) echo this shell is not interactive;;
esac
So “launch zsh if this is an interactive shell” should be written
case $- in
*i*) exec zsh;;
esac
But even that is not a good idea: it prevents opening a bash shell, which is useful even if you use zsh. Forget about this blog post and instead simply configure your shortcut that opens a terminal to run zsh instead of bash. Don't arrange things so that “whenever you open the Bash application on Windows, it will now start up with the Zsh shell”: when you want zsh, open the Zsh application.
bash
can read.bashrc
even when not interactive (like inssh host cmd
wherebash
is the login shell of the user on host, orbash --login -c 'some code'
where the.bash_profile
sources the.bashrc
).case $- in *i*)...
is the correct way to test if a shell is interactive. – Stéphane Chazelas Aug 31 '17 at 13:34i
will be set (and in modern shells that can be tested withif
instead of having to usecase
). But there are many use cases where one only cares if stdout (or stdin, or stderr...) is attached to a terminal. – Mark Reed Nov 21 '17 at 15:54