i Don't Use $SHELL to Check Which Shell You Are Using · Dark Matter Industries

Don't Use $SHELL to Check Which Shell You Are Using

My preferred shell is zsh these days. I started with sh and bash, then got sidelined into tcsh after a mathematician friend and colleague at the Max Planck Institute fired up the shell on my Silicon Graphics work station and showed me the cool things it could do.

Then, as Apple started finding its way again and more and more of their machines entered my life I circled back to bash. This just made my life easier on Darwin (and also, later, any VMs or cloud compute engines that I spun up).

I also started playing around with zsh some time ago, fascinated by Oh My Zsh. Then, Apple decided to set zsh as the default shell in macOS starting with Catalina in June 2019 – the company preferred the licensing terms of zsh over bash. This means that I now use zsh 80% of the time. But I do flip back and forth between various shells.

So how do you know which shell you are in?

Your first instinct would be to “echo $SHELL”. Now, $SHELL is a variable set by the user: in theory it should reflect the shell you are using, but there are situations where it fails. And the reason I wrote this entry is because I have just come across one such situation:

% echo $SHELL
/bin/bash

The above was executed in a zsh. This happened because:

  1. I spawned a zsh from a bash shell;
  2. I have not yet set any dot-file profiles etc for zsh on this machine.

Getting The Truth

There is a foolproof way to get the ground truth.

The first thing to note is that the unix shell variable $ returns the PID (process ID) of the current process. Hence if you echo’d that in a shell, you’d get the shell’s PID:

% echo $$
50110

This variable can also be used with ps:

% ps $$   
  PID   TT  STAT      TIME COMMAND
50110 s001  S      0:00.33 -zsh

Another way, but may be confusing if you are new to the shell, is to use the positional variable $0.

$0 is where the name of the script of a sourced script, or function name for a script function. (For zsh see the manpage zshall and search for “Parameters Set By The Shell”.)

Hence in:

 $ ./myShellScript.sh -i input.file -o output.file

$0 would be ./myShellScript.sh, $1 is -i etc.

However, if you echo $0 in the command line, it is the shell that executes it (it really is a shorthand for /bin/[bash, zsh etc] echo $0), hence will return the shell.

% echo $0
-zsh

Additionally if the shell has a dash - before the name it indicates that it’s a login shell.

And there you have it: the ground truth.