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.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

This question already has an answer here:

After looking around for a while I've found several good pages describing how to check and see if a bash script is running interactively and there seem to be several methods, but one of them that I keep seeing over and over is checking the variable $- for the presence of i to signify that it is interactive.

I'm looking for a way to use an if statement that would work with both /bin/bash and /bin/sh (which is typically aliased to /bin/dash on Ubuntu systems), or in fewer words
"an interactive if test that is universal as possible"

For bash it seems these things should work:

Case Statement

case "$-" in
*i*)    echo This shell is interactive ;;
*)  echo This shell is not interactive ;;

If Statement

if [[ $- == *i* ]]

But $- is apparently not set in dash. Possibly because $- is supposed to be the Flags passed to script variable which

was originally a ksh construct adopted into Bash, and unfortunately it does not seem to work reliably in Bash scripts... [ for it's intended purpose however] ...One possible use for it is to have a script self-test whether it is interactive.

So is there an (relatively simple) if test that can be used both with bash and dash?

Or am I just "doing it wrong?"

ps: I have been under the impression that dash is faster than bash, and unless the script needs "bash specific" functions it would be better to hashbang it as #!/bin/sh and let it use the system-default shell. I get that checking for an interactive shell in the way mentioned above is "bash specific" but it seems odd to think there is not a more universal way. In the script I'm working on I don't need any other bash-specific functionality.

share|improve this question

marked as duplicate by Chris Down, Anthon, Zelda, slm, terdon Feb 4 '14 at 19:32

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

What makes you think dash doesn't set $-? Both your if and your case statements work exactly as you've posted them in bash, bash called as sh (which makes a difference, yes), zsh, csh, ksh, tcsh, fish and dash. I checked. – terdon Feb 4 '14 at 19:31
up vote 0 down vote accepted

A very common (if not utterly foolproof) way to check for an interactive terminal is to check whether PS1 is set:

if [[ -z "$PS1" ]]; then
    echo "Probably run as a script."
    echo "Probably interactive."

Another alternative is checking for the i option in $-:

case "$-" in
       echo "Probably interactive"
       echo "Probably scripted"

There is also the -t option for test (aka [ and its cousin, [[):

fd=0 # stdin
if [[ -t "$fd" ]]; then
    echo "Interactive"
    echo "Scripted"

Tip of the hat to the Linux Documentation Project.

dash and sh may not have [ and [[ available, so you might have to explicitly use test, e. g.:

if test -t "$fd"; then  # you might need /path/to/test
    echo "Interactive"
    echo "Scripted"

Since test is its own binary, I'm pretty certain that anything using test -t is shell-agnostic.

share|improve this answer
test -t has nothing to do with being interactive or not, it has to do with being connected to a terminal. – Chris Down Feb 4 '14 at 18:08

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