Sign up ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

How to check what shell I am using in a terminal? What is the shell I am using in MacOS?

share|improve this question
I'm pretty sure this is a dupe... do I want to find it... – xenoterracide Mar 18 '11 at 11:55
@xenoterracide: at least… . geekosaur's answer is more complete, so i voted to close the earlier question. – Gilles Mar 30 '11 at 17:33
echo $SHELL, no? – innocent-world Aug 23 '13 at 11:49

9 Answers 9

The pid of the running shell is given by the var $$ (in most shells).

Using that number we can find which regular (program) file is open by that pid:

lsof -a -p $$ -d txt

which gives an answer like:

ksh     18177 bize txt    REG    9,2  1489008  497 /bin/ksh93

In some systems the libraries are not linked in memory, and appear as open files. To filter out such programs we could list only files in /bin/ and /usr/bin/ (common places for shells, but more could be added). And using awk to select the last value will make the line more portable:

$ lsof -a +D /bin +D /usr/bin -p $$ -d txt | awk 'NR>1 {print $NF}';:

That gives a clean link to the file that is kept open by the process and that holds « program text » i.e. code and data (executable).

The alternative: ps -p$$ -o cmd= gives the command that was written on the command line, which is almost always the name of the running shell, but it does not have to be so.

The last ;: are important to keep the shell running in some corner cases of ksh and zsh.

share|improve this answer
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. – Stéphane Chazelas Sep 7 at 16:12
Yes, it now only selects the entries in /bin and /usr/bin – Stéphane Chazelas Sep 8 at 9:57

Several ways, from most to least reliable (and most-to-least "heavy"):

  1. ps -p$$ -ocmd=. (On Solaris, this may need to be fname instead of cmd. On OSX and on BSD should be command instead of cmd.)
  2. Check for $BASH_VERSION, $ZSH_VERSION, and other shell-specific variables.
  3. Check $SHELL; this is a last resort, as it specifies your default shell and not necessarily the current shell.
share|improve this answer
Should you mention $0 too? – Mikel Mar 18 '11 at 2:41
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. – geekosaur Mar 18 '11 at 2:44
ps -p$$ -ocmd="" is prettier :-) – asoundmove Mar 18 '11 at 3:51
@geekosaur: maybe so, but $0 still seems more useful than $SHELL: wouldn't you agree? You could always pipe it through sed to remove the '-'. – iconoclast Aug 29 '12 at 21:49
If 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 of csh, 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. – Keith Thompson Mar 18 '14 at 1:51

I set $MYSHELL for future tests in my shell-agnostic ~/.aliases:

if [ -n "$ZSH_VERSION" ] && type zstyle >/dev/null 2>&1; then        # zsh
  MYSHELL=`command -v zsh`
elif [ -x "$BASH" ] && shopt -q >/dev/null 2>&1; then                # bash
  MYSHELL=`command -v bash`
elif [ -x "$shell" ] && which setenv |grep builtin >/dev/null; then  # tcsh
  echo "DANGER: this script is likely not compatible with C shells!"
  sleep 5
  setenv MYSHELL "$shell"

# verify
if [ ! -x "$MYSHELL" ]; then
  MYSHELL=`command -v "$(ps $$ |awk 'NR == 2 { print $NF }')"`
  [ -x "$MYSHELL" ] || MYSHELL="${SHELL:-/bin/sh}"  # default if verify fails

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.)

share|improve this answer
ps -p $$ | tail -n 1 | awk -F '\-' '{print $2}'
share|improve this answer
Hi and welcome to the site. This is not a good answer because 1) it basically repeats what others have said but does so in a more complex way 2) has no explanation of how it works or what it does 3) (minor point) causes a warning by awk since the - does not need to be escaped and 4) fails if the output of ps -p $$ does not have any -. – terdon Jun 19 '14 at 14:12

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
share|improve this answer
this gives me my current directory name; also, under csh and tcsh it gives me Ambiguous output redirect. – iconoclast Aug 7 at 0:17

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 $$
share|improve this answer

This works too:

env | grep SHELL
share|improve this answer
Or not. See point 3. in geekosaur's answer. – manatwork Mar 14 '12 at 17:02

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 $$.

share|improve this answer
ps | grep $$ can still give false positives if, for example, your current process is 1234 and there's a process 12345. – Keith Thompson Mar 18 '14 at 1:48

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
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.