In general, you can't. Redirections don't appear as arguments to the running command. Even if they did, you wouldn't be able to tell where the script output goes in all cases. Consider these two:
bash -c 'somecmd > /dev/null; othercmd'
and
bash -c 'somecmd; othercmd' > /dev/null
In the first case, the output of somecmd
is redirected to /dev/null
, but in the second case, the output of the whole shell is redirected, including both somecmd
and othercmd
. Seeing the command line of somecmd
in the second case wouldn't tell how the output is redirected.
That said, it appears Bash's DEBUG
trap can be used for this.
$ trap 'export CMDLINE=$BASH_COMMAND' DEBUG
$ env 2>/dev/null |grep CMD
CMDLINE=env 2> /dev/null
The trap exports the command to be run as CMDLINE
, which we can see is exported since it shows in the output of env
. Note that the full pipeline is not shown, just the one command.
That said, in most cases there are better ways to deal with things than trying to second-guess the user's redirections. Many commands check if the output goes to a terminal and change their behavior based on that.
To check if stdout is a terminal, you can use [ -t 1 ]
:
$ if [ -t 1 ]; then echo terminal; else echo not terminal; fi |cat
not terminal
This is most often used to disable some interactive functionality or extraneous output in case the output doesn't go to a terminal and hence, by assumption, to a user.
If just testing if a file descriptor points to a terminal isn't enough, it might be easiest to arrange to pass an additional argument to the program to tell it what mode to operate in. That is, instead of caring about redirections, have the program do one thing if started with someprog --mode=cron
, another if started with someprog --mode=batch
and run interactively if started without a --mode
argument. (Make interactive or command line mode the default so that the user doesn't need to manually type --mode=commandline
each time they run it by hand.)