I only want to determine from my POSIX shell script, if it is running interactively, but for some reason, the following function:

    printf '%s' ${-} | grep -F i > /dev/null 2>&1

returns false even if I run the script in terminal. Am I doing it wrong, or is the definition of interactive script somehow different from my plain idea of running the script by a user in terminal?

Snippet of the code:


set -u

#   echo $- returns only u
    printf '%s' ${-} | grep i > /dev/null 2>&1

    # redirect all output from this function to standard error stream
    if running_interactively
        exec >&2
        echo wrong again, smart ass

print_error_and_exit someArgs

1 Answer 1


A shell script is, unless it's sourced by an interactive shell, very seldom run in an interactive shell environment. This means that $- would not include an i.

What you could check is to see whether standard input is connected to a terminal or not. This is done using the -t test with an argument of 0 (the file descriptor of the standard input stream):

running_interactively () { [ -t 0 ]; }

This assumes that by "is running interactively" you mean "able to read input directly from a terminal".

An additional test on file descriptor 2 (standard error) would also be possible as a test of being able to do full interaction with the user in a script. User interaction mainly happens on standard input (user input) and standard error (prompts, diagnostic messages, etc.):

running_interactively () { [ -t 0 ] && [ -t 2 ]; }

However, testing on file descriptor 1 (standard output) would fail if the output of the script was redirected or piped.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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