0

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 ;;
esac

If Statement

if [[ $- == *i* ]]
then
    do_interactive_stuff
fi

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.

cwd
  • 45,389
  • 2
    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 04 '14 at 19:31

1 Answers1

0

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."
else
    echo "Probably interactive."
fi

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

case "$-" in
   *i*)
       echo "Probably interactive"
       ;;
   *)
       echo "Probably scripted"
       ;;
esac

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

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

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

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

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

DopeGhoti
  • 76,081
  • test -t has nothing to do with being interactive or not, it has to do with being connected to a terminal. – Chris Down Feb 04 '14 at 18:08
  • https://stackoverflow.com/questions/2683279/how-to-detect-if-a-script-is-being-sourced alternatives – floer32 Apr 06 '19 at 03:25