Command-Line Interface
Shell Scripting
Programming
Terminal Commands
Tech Tips

How to determine the current interactive shell that I'm in (command-line)

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Determining which shell you are currently using is important for writing compatible scripts, setting up dotfiles, and debugging environment issues. The most reliable method is ps -p $$ -o comm=, which queries the process table for the current shell process. Other methods like echo $0, $SHELL, and shell-specific variables each have caveats. $SHELL tells you the default login shell, not necessarily the shell you are currently running in.

Quick Methods

ps -p $$ (Most Reliable)

bash
ps -p $$ -o comm=
# bash
# or: zsh, fish, sh, dash, etc.

$$ is the PID of the current shell process. ps -p $$ -o comm= prints just the command name without headers. This works in bash, zsh, sh, dash, and ksh.

echo $0

bash
1echo $0
2# -bash       (login shell, note the leading dash)
3# bash        (non-login shell)
4# /bin/zsh    (may show full path)

$0 contains the name or path of the current shell. A leading - indicates a login shell. This works in most POSIX shells but not in fish.

$SHELL (Default Shell, Not Current)

bash
echo $SHELL
# /bin/zsh    (your default login shell)

$SHELL is set to your login shell from /etc/passwd or Directory Services. It does NOT change when you switch shells. If your default is zsh but you run bash, $SHELL still says /bin/zsh.

bash
1# Demonstrate the difference
2echo $SHELL     # /bin/zsh (login shell)
3bash            # Switch to bash
4echo $SHELL     # /bin/zsh (still shows zsh!)
5ps -p $$ -o comm=  # bash (correctly shows current shell)

Shell-Specific Variables

Each shell sets unique variables you can test:

bash
1# Bash
2echo $BASH_VERSION
3# 5.2.26(1)-release
4
5# Zsh
6echo $ZSH_VERSION
7# 5.9
8
9# Fish
10echo $FISH_VERSION
11# 3.7.0
12
13# Ksh
14echo $KSH_VERSION
15# Version AJM 93u+m/1.0.7

Detection Script

bash
1detect_shell() {
2    if [ -n "$BASH_VERSION" ]; then
3        echo "bash $BASH_VERSION"
4    elif [ -n "$ZSH_VERSION" ]; then
5        echo "zsh $ZSH_VERSION"
6    elif [ -n "$FISH_VERSION" ]; then
7        echo "fish $FISH_VERSION"
8    elif [ -n "$KSH_VERSION" ]; then
9        echo "ksh $KSH_VERSION"
10    else
11        echo "unknown: $(ps -p $$ -o comm=)"
12    fi
13}
14
15detect_shell

Checking Shell Features

bash
1# Check if the shell supports a specific feature
2# Arrays (bash/zsh, not sh/dash)
3if (eval 'arr=(1 2 3)') 2>/dev/null; then
4    echo "Shell supports arrays"
5fi
6
7# Check if running in POSIX mode
8if [ -n "$POSIXLY_CORRECT" ]; then
9    echo "Running in POSIX mode"
10fi

Methods on Different Systems

macOS

bash
1# Default shell (since macOS Catalina, it's zsh)
2dscl . -read /Users/$USER UserShell
3# UserShell: /bin/zsh
4
5# Current shell
6ps -p $$ -o comm=
7# zsh
8
9# Change default shell
10chsh -s /bin/bash

Linux

bash
1# Default shell from /etc/passwd
2grep $USER /etc/passwd | cut -d: -f7
3# /bin/bash
4
5# All available shells
6cat /etc/shells
7# /bin/sh
8# /bin/bash
9# /bin/zsh
10# /usr/bin/fish
11
12# Current shell
13ps -p $$ -o comm=

Within a Script

bash
1#!/bin/bash
2# Inside a script, $0 is the script name, not the shell
3echo $0         # ./myscript.sh
4echo $SHELL     # /bin/zsh (login shell, not the script's interpreter)
5
6# The shebang line determines which shell runs the script
7# Use /proc/self/exe on Linux to find the interpreter
8readlink /proc/$$/exe 2>/dev/null || ps -p $$ -o comm=

Login Shell vs Non-Login Shell

bash
1# Check if current shell is a login shell
2
3# Bash
4shopt -q login_shell && echo "login" || echo "non-login"
5
6# Zsh
7[[ -o login ]] && echo "login" || echo "non-login"
8
9# Generic — login shells have a leading dash in $0
10case "$0" in
11    -*) echo "login shell" ;;
12    *)  echo "non-login shell" ;;
13esac

Login shells read different config files:

  • bash login: ~/.bash_profile or ~/.profile
  • bash non-login: ~/.bashrc
  • zsh login: ~/.zprofile, ~/.zshrc
  • zsh non-login: ~/.zshrc

Common Pitfalls

  • Relying on $SHELL for the current shell: $SHELL is the default login shell, not the currently running shell. If you switched shells with bash or zsh, $SHELL still shows the original.
  • Assuming $0 always returns the shell name: Inside scripts, $0 is the script filename. In subshells, it may be -bash (with a leading dash) for login shells. Parse carefully.
  • Fish shell incompatibility: Fish does not support POSIX syntax ($?, $$, [ -n ]). Use echo $FISH_VERSION or status fish-path for detection in fish.
  • Confusing sh with bash: On many systems, /bin/sh is a symlink to bash or dash. Running sh may invoke bash in POSIX compatibility mode, which disables bash-specific features like arrays.
  • Not checking the shell before using shell-specific features: Bashisms like [[ ]], (( )), and arrays break in sh, dash, and other POSIX-only shells. Always check the shell or use POSIX-compatible syntax for portable scripts.

Summary

  • ps -p $$ -o comm= is the most reliable way to determine the current shell
  • $SHELL shows your default login shell, not the currently running shell
  • Shell-specific variables ($BASH_VERSION, $ZSH_VERSION, $FISH_VERSION) confirm both the shell and its version
  • $0 shows the shell name but includes a leading - for login shells and shows script names inside scripts
  • Always test for the current shell before using shell-specific features in portable scripts

Course illustration
Course illustration

All Rights Reserved.