How to check if a shell is login/interactive/batch

I think I understand the differences between an interactive, a login and a batch shell. See the following links for more help:

My question is, how can I test with a command/condition if I am on an interactive, a login or a batch shell?

I am looking for a command or condition (that returns true or false) and that I could also place in an if statement. For example:

if [[ condition ]]
   echo "This is a login shell"
fi

csh / tcsh

For csh and tcsh I have the following in my .cshrc file:

if($?prompt) then               # Only interactive shells set $prompt
    ...
endif

Specifically for tcsh, the variable loginsh is set for a login shell:

if($?loginsh) then              # A login shell..
    ...
endif

(tcsh also has a variable shlvl which is set to the number of nested shells, where the login shell has a value of 1.)

Answered By: Andrew Stein

Another way is to check the result of tty

if [ "`tty`" != "not a tty" ]; then
Answered By: Adrian Cornish

I’m assuming a bash shell, or similar, since there is no shell listed in the tags.

To check if you are in an interactive shell:

[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'

To check if you are in a login shell:

shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'

By "batch", I assume you mean "not interactive", so the check for an interactive shell should suffice.

Answered By: Chris Down

In any Bourne-style shell, the i option indicates whether the shell is interactive:

case $- in
  *i*) echo "This shell is interactive";;
  *) echo "This is a script";;
esac

There’s no portable and fully reliable way to test for a login shell. Ksh and zsh add l to $-. Bash sets the login_shell option, which you can query with shopt -q login_shell. Portably, test whether $0 starts with a -: shells normally know that they’re login shells because the caller added a - prefix to argument zero (normally the name or path of the executable). This fails to detect shell-specific ways of invoking a login shell (e.g. ash -l).

i is not the correct option to look for. -i is to force an otherwise
non-interactive shell to become interactive. The correct auto-enabled
option is -s, but Bash unfortunately does not handle this correctly.

You need to check whether $- contains s (this is granted to be
auto-activated) or whether it contains i (this is not granted to
be auto-activated but officially only coupled to the -i command line
option of the shell).

Answered By: schily

fish shell

Here’s the answer for fish in case any other users stumble upon this page.

if status --is-interactive
    # fish is interactive - that is, connected to a keyboard.
    # do stuff...
end

if status --is-login
    # fish is a login shell - that is, should perform login tasks such  as  setting  up PATH
    # do stuff...
end

echo "darn, I really wanted to have to use globs or at least a case statement"

fish docs ref

Answered By: ohspite

UNIX/Linux has a command to check if you are on a terminal.

if tty -s
then
echo Terminal
else
echo Not on a terminal
fi
Answered By: Paul

You can check to see if stdin is a terminal:

if [ -t 0 ]
then
    echo "Hit enter"
    read ans
fi
Answered By: Angelo

To check whether a script runs in an interactive or non-interactive shell,
I check in my scripts for the presence of a prompt stored in the $PS1 variable:

if [ -z $PS1 ] # no prompt?
### if [ -v PS1 ]   # On Bash 4.2+ ...
then
  # non-interactive
  ...
else
  # interactive
  ...
fi

This I learned here: https://www.tldp.org/LDP/abs/html/intandnonint.html

Answered By: Christian Herenz

Curiously, scripts launched off the desktop in MacOS have the same environment as those started by hand. (They have their stdin as a teletype tty, they have their login_shell shopt unset and their "$-" as ehxB)

If my preferred way of bringing a script to the desktop is to create a symlink from ~/Desktop to the script, I can only guess that it was launched with a click by checking if "$0" is an absolute path (i.e. starts with a slash).

Answered By: eel ghEEz

for Zsh

# Checking Interactive v.s. Non-Interactive
[[ -o interactive ]] && echo "Interactive" || echo "Non-Interactive"
#
# Checking Login v.s. Non-Login
[[ -o login ]] && echo "Login" || echo "Non-Login"

Ref: 2.1.1: What is a login shell? Simple tests

Answered By: YaOzI
Categories: Answers Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.