How to check what shell I am using in a terminal? What is the shell I am using in MacOS?
13 Answers
Several ways, from most to least reliable (and most-to-least "heavy"):
ps -p$$ -ocmd=
. (On Solaris, this may need to beps -p$$ -ofname=
and on macOS and on BSD should beps -p$$ -ocommand=
.)- Check for
$BASH_VERSION
,$ZSH_VERSION
, and other shell-specific variables. - Check
$SHELL
; this is a last resort, as it specifies your default shell and not necessarily the current shell.
-
8
-
I don't like
$0
because it's more complicated: (1) it may be just the basename, (2) it may have '-' on the front to designate it as a login shell. Mar 18, 2011 at 2:44 -
1@geekosaur: maybe so, but
$0
still seems more useful than$SHELL
: wouldn't you agree? You could always pipe it throughsed
to remove the '-'. Aug 29, 2012 at 21:49 -
5On Mac, #1 is
ps -p $$ -o comm=""
. Also, for those wondering, $$ is the shell process ID.– duozmoOct 19, 2013 at 18:00 -
2If you're running
tcsh
,$tcsh
and$version
will be set. These are shell variables, not environment variables. If you're running a non-tcsh version ofcsh
, I don't think there are any distinctive variables. And of course the syntax used to check variables differs between csh/tcsh on the one hand, and sh/ksh/bash/zsh on the other. Mar 18, 2014 at 1:51
I've found that the following works in the four shells I have installed on my system (bash, dash, zsh, csh):
$ ps -p $$
The following works on zsh, bash, and dash, but not on csh:
$ echo $0
-
2
-
I think that @jiliagre's answer is probably would I would use today. On fish
%self
can be used in place of$$
– Steven DAug 27, 2016 at 23:00 -
1It would be great if you explained what you are doing, why this works, what the
$$
is etc Aug 5, 2020 at 18:00
As the question asks for the shell used and does not talk about the potential arguments passed to it, here is a way that avoid showing them:
$ ps -o comm= -p $$
ksh93
There are two really simple ways:
Using ps command:
ps -o comm= $$
or
ps -h -o comm -p $$
where:
-h
or finishing all options with=
for not showing any header.-o comm
for showing only the process basename (bash
instead of/bin/bash
).-p <PID>
list only process whith PID form list suplied.
Using the /proc process information pseudo-file system:
cat /proc/$$/comm
This option behaves exactly as the
ps
command above.or
readlink /proc/$$/exe
This
/proc/PID/exe
links to the file being executed, which in this case would point to /bin/bash, /bin/ksh, etc.For getting only the name of the shell you can just use
basename $(readlink /proc/$$/exe)
This is the only option that will always give the same result even if you are in an script, sourced code, or terminal, as links to the binary of the shell interpreter in use.
Warning You must be aware that this will show the ultimate binary, so ksh may be linked to ksh93 or sh to bash.
The usage of /proc
is really useful via the /proc/self
, which links to the PID of the current command.
-
2
basename $(readlink /proc/$$/exe)
is Korn/POSIX shell syntax. Won't work in csh/tcsh/rc/es/akanga/fish.$$
won't work inrc
/es
/akanga
/fish
. Oct 9, 2020 at 7:27 -
basename $(readlink /proc/$$/exe)
is the only command here that could work for me in a docker image with nops
installed.– FlavinApr 21, 2021 at 13:15
A note about some lighter implementations (Android phones, busybox, etc.): ps
doesn't always have support for the -p
switch, but you can accomplish the search with a command like ps | grep "^$$ "
. (This grep
regex will uniquely identify the PID, so there will not be any false positives.)
-
10
ps | grep $$
can still give false positives if, for example, your current process is1234
and there's a process12345
. Mar 18, 2014 at 1:48
A mix of all the other answers, compatible with Mac (comm), Solaris (fname) and Linux (cmd):
ps -p$$ -o cmd="",comm="",fname="" 2>/dev/null | sed 's/^-//' | grep -oE '\w+' | head -n1
-
this gives me my current directory name; also, under
csh
andtcsh
it gives meAmbiguous output redirect.
Aug 7, 2015 at 0:17 -
This is also what Anaconda uses (version 2022.05) in it's
[env]/bin/activate
script to detect shell type. A comment in that file explicitly links to this answer. Jun 10, 2022 at 11:41
If you have it saved in your environment variables you can use the following:
echo $SHELL
For accuracy in many different shells you should use
ps -p $$
Why does this work?
echo $$ # 998
What is that number?
It's the process id
of the current shell.
$
expands to the same value as the current shell.
$$
process ID of the parent in a sub shell
If you only want then name of the shell you could use
ps -p $$ | awk '{if(NR>1)print}' | awk '$0=$NF' | tr -d -
In a nutshell we are taking the output of the process sub shell and piping it to some formatting tools awk, sed and tr all work for this, removing the first 3 columns, the first line of output, and then the - gives just the name of the shell. Consider putting that into a function for ease later.
-
That will most likely return the pathname of the shell executable of your login shell. It is not certain that the login shell is what you are currently running though.– Kusalananda ♦Apr 10, 2019 at 6:39
-
I have updated my answer to provide more value and understanding. Aug 5, 2020 at 18:16
I set $MYSHELL
for future tests in my shell-agnostic ~/.aliases
:
unset MYSHELL
if [ -n "$ZSH_VERSION" ] && type zstyle >/dev/null 2>&1; then # zsh
MYSHELL=`command -v zsh`
elif [ -x "$BASH_VERSION" ] && type caller >/dev/null 2>&1; then # bash
MYSHELL=`command -v bash`
elif [ -x "$shell" ] && which setenv |grep -l builtin >/dev/null; then # tcsh
echo "DANGER: this script is likely not compatible with C shells!"
sleep 5
setenv MYSHELL "$shell"
fi
# verify
if [ ! -x "$MYSHELL" ]; then
MYSHELL=`command -v "$(ps $$ |awk 'NR == 2 { print $NF }')"`
[ -x "$MYSHELL" ] || MYSHELL="${SHELL:-/bin/sh}" # default if verify fails
fi
The tcsh
section is likely unwise to roll into a POSIX-style script since it's so radically different (thus the warning and five second pause). (For one, csh
-style shells can't do 2>/dev/null
or >&2
, as noted in the famous Csh Programming Considered Harmful rant.)
The pid of the running shell is given by the var $$ (in most shells).
whichsh="`ps -o pid,args| awk '$1=='"$$"'{print $2}'`"
echo "$whichsh"
Using backticks to make jsh (Heirlomm shell) work.
In many shells the direct test of ps -o args= -p $$
works, but busybox ash
fails on that (solved).
The check that $1
must be equal to $$
removes most false positives.
The last ;:
are used to keep the shell running for ksh and zsh.
Tests on more systems will help, please make a comment if it doesn't work for you.
Does not work in csh
type of shells.
-
On OS/X, in my tests, I get at least 3 lines, one for the shell, one for
/usr/lib/dyld
, one for/private/var/db/dyld/dyld_shared_cache_x86_64
. Sep 7, 2015 at 16:12 -
-
@StéphaneChazelas Maybe it is better now?– user79743Feb 25, 2016 at 22:29
Good question me too on my Mac had the same doubt.
Another method, dirty but "it works", it really simple; you should launch a command that does not exist. The the shell reply the classical "command not found", but first shows its name. :-)
~$ piripicchio
-bash: piripicchio: command not found
and
~ % piripicchio
zsh: command not found: piripicchio`
Also, you could note that zsh prompt is "%" and bash is "$" but my root on bash has "%" too.
echo ${0//-/}
This one returns bash
or zsh
even if it's a login shell (ie. starting with -
).
-
This would only work in shells that support the non-standard expansion
${variable//pattern/replacement}
.– Kusalananda ♦Nov 14, 2022 at 7:23
You can simply use echo $0
command to check which shell you are using and <name_of_the_shell> --version
to check the version of the shell. (eg. bash --version
).
-
-
Note that
--version
is not a standard option, so it won't work with all shells.– Kusalananda ♦Nov 14, 2022 at 7:23
This works too:
env | grep SHELL
-
3
echo #SHELL
is not quite it. See # 3 in the Answer by geekosaur.xterm -e /bin/cat
but I am not happy calling/bin/cat
a shell.