Only the csh
/ tcsh
shells set the $shell
variable. So you'd only get the path of a shell with that echo $shell
command if run from one those shells¹, maybe you found that in a section of that book that talks about those.
login
or other login managers set the SHELL
environment variable to your login shell (the shell mentioned in the passwd
database for your account), which shells will invariably map to their corresponding $SHELL
variable and it's the environment variable you want to set to your preferred shell for things like terminal emulators or vi
to start it instead of your login shell.
But that's not necessarily the shell that is currently in use.
It would be the case if you have started your terminal emulator in an environment where that $SHELL
variable had not been modified since login and your terminal emulator is not otherwise configured to start a different shell (or other command) from the one stored in $SHELL
, and a different shell has not been started or the $SHELL
variable modified as part of your $SHELL
shell startup sequence.
There is no shell variable that will tell you which shell is in use regardless of the shell though beside (t)csh's $shell
, there's bash
's $BASH
or $BASH_VERSION
/$BASH_VERSINFO
, zsh
's $ZSH_VERSION
, $KSH_VERSION
in some ksh
implementations, ${.sh.version}
in ksh93, $YASH_VERSION
in yash
which can help you tell which shell you're running.
On Linux, you can also do readlink "/proc/$$/exe"
to get the path of the shell interpreter with those shells where $$
expands to the pid of the process that executed the interpreter (Bourne-like, csh-like; see $fish_pid
in fish
, $pid
in rc
-like shells).
More portably, sh -c 'ps -o comm= -p "$PPID"'
will give you the name of the parent process of sh
, which should be running the shell currently in use, and the name of that process should be derived from the basename of the shell interpreter executable. All common shells should interpret that code the same, an all systems in scope of this site should have a sh
and ps
commands that can understand that.
To print the contents of a variable followed by a newline in Bourne-like shells, the syntax is:
printf '%s\n' "$SHELL"
Or in csh
:
printf '%s\n' $SHELL:q
Or in rc
-like or fish
or zsh
shells:
printf '%s\n' $SHELL
not echo $SHELL
(though when you don't know which shell you're running, that's probably a good enough approximation that should work in most shells in most cases).
To know which is your login shell, as stored in the passwd
database, on many systems, you can do (Bourne syntax):
getent -- passwd "$LOGNAME" | cut -d: -f7
Or on systems without a getent
utility:
perl -le 'print((getpwnam getlogin)[8])'
¹ but only if $shell
doesn't contain wildcard characters, and could also be mangled by echo
which can't output arbitrary data