8

In bash, is there a way to know if a given script has been invoked with:

$ myscript.sh myfile

or:

$ myscript.sh < myfile

Inside some scripts I always have accessed the contents of myfile with $1, but now I'd like to change the behavior as different cases.

EDIT: I also would like a third case when invoked without any redirection:

$ myscript.sh

2 Answers 2

14

EDIT: changed -t to -t 0, which does correctly detect input from terminal or file.

I think the key here is knowing whether your input is coming from a terminal or from a file. There is a test for this (man test, see -t).

Assuming you're running a bash script:

if [ -t 0 ]; then
    echo "Input from terminal"
    if [ $# -eq 0 ]; then
        echo "No input files specified on command line.  Error." >&2
    else
        echo "Input file given on command line.  It is $1"
    fi
else
    echo "Input coming from stdin"
fi

You can handle the different scenarios by substituting actual code in for the echo statements above.

Update, quickie test script:

#!/bin/bash
[ -t 0 ] && echo "t is true" || echo "t is false"

Running:

$ test.sh testfile
t is true
$ test.sh < testfile
t is false
$
5
  • -t always evaluates to true running the script from the command line with < myfile :( Jun 27, 2011 at 7:28
  • @mschonaker - Using -t 0 gives the correct results. Updated answer.
    – unpythonic
    Jun 27, 2011 at 7:39
  • @MarkMann What does the 0 do? What is the difference? It's not in the documentation.
    – Ivan V.
    Feb 5, 2016 at 21:47
  • 1
    @IvanV. - The zero is the file descriptor to test. Standard input is associated with 0, standard output with 1 and standard error with 2. If I wanted to check if my output was going to a terminal I would use [ -t 1 ]
    – unpythonic
    Feb 5, 2016 at 22:16
  • @MarkMann Thanks, I thought it might be that, or some kind of Boolean check.
    – Ivan V.
    Feb 6, 2016 at 11:32
6

In general, the expressions $1, $2, etc. expand to the 1st, 2nd, etc. argument given on the script command line.

So, when you invoke a script as:

myscript.sh myfile

then $1 within the script expands to myfile (and $2, $3, etc. all are the empty string).

When you invoke a script as:

myscript < myfile

the redirection of STDIN from myfile is done by the parent shell, so the script is actually called with no arguments and $1 expands to the empty string.

1
  • How do I detect if called with no arguments in the command line (the third case)? Sorry if you answered before my edit. Thanks. Jun 27, 2011 at 7:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .