I have a script in ksh; depending whether there is a redirection from the command line, I redirect the output via a exec 1>file. How can I test from inside the script itself if the command calling it has redirected its output?

I tried using $@, $*, $0, and even a ps on the PID of the script (hopefully there is a shebang) but the redirection never appears.

The script is running on AIX in this case.

  • 1
    Redirections never appear as any of the argument to any command as they are acted on by the calling shell before the command is executed. This sounds a lot like an XY-problem. What is it you'd like to achieve?
    – Kusalananda
    Jan 29, 2019 at 10:23
  • 1st lien of the question. Script will redirect or not it's own content depending of a redirection call or not. I try to know from the script how the call was made from the parent. Reirection check is the way i could know how to manage it but maybe the good point of view. I don't know wo and how the script will be used so can't set info before Jan 29, 2019 at 10:40
  • Seems like documentation of the script and how it's supposed to be used might be in order. If a user knows to redirect its output, always, then document that and be done with it. Don't try to babysit the user any more than that.
    – Kusalananda
    Jan 29, 2019 at 19:49

3 Answers 3


On AIX, the stdout file descriptor is available at /proc/$$/fd/1, so you could test it for being a regular file or not:

if [ -f "/proc/$$/fd/1" ]
  echo stdout has already been redirected
  echo redirecting stdout
  exec 1>file
  echo some output

/bin/sh is hardlinked to /bin/ksh, so you get the same behavior in either shell.

You could test separately for stdout having been redirected to /dev/null, if you wanted:

if [ "/proc/$$/fd/1" -ef /dev/null ]; then : ...; fi
  • Excatly what i'm looking for, fd/2 is the error default channel and other created channel (if any). Also the /dev/null special case is helpfull Jan 30, 2019 at 13:17
  • This works in Linux too.
    – lord_nimon
    Aug 25, 2022 at 19:53

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'


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.

$ 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.)

  • the test of terminal is not elligible because it is run from 1) comand line, 2) cron 3) external agent running a subshell (agent are not terminal session). This is the tricky point. I haven't thought about DEBUG, good point Jan 29, 2019 at 12:43
  • bad luck, cannot have this info without previously trap, that is not possible ... Jan 29, 2019 at 13:23
  • 1
    @NeronLeVelu, well, I didn't know (and still really don't know) what the actual use case was, so I mentioned testing for terminals since it's one common case. And yes, the DEBUG trap only works if set in the calling shell, and it might not be easy to use within, say, cron. (Though you could of course manually set the environment variable, but then you might just directly pass whatever information it is you're eventually interpreting from the redirections. Edited.)
    – ilkkachu
    Jan 29, 2019 at 13:27
  • that's exactly my problem. i check via a lsof but assuming the PID of the script and using a inode reference. Assuming lot of interpretation is not the most reliable method Jan 29, 2019 at 14:42

In my testing, on Linux (Debian 10.12) with Bash 5 (GNU bash, version 5.0.3(1)-release (x86_64-pc-linux-gnu)), you can use the [ -p test.

  • Consider a script test.sh
    ls -lah /proc/$$/fd/1
    if [ -p "/proc/$$/fd/1" ]; then echo "pipe"; else echo "nopipe"; fi
    exec 1> >( cat ) 2>&1
    ls -lah /proc/$$/fd/1
    if [ -p "/proc/$$/fd/1" ]; then echo "pipe"; else echo "nopipe"; fi
  • Execute the script without and with redirection:
    $ ./test.sh
    lrwx------ 1 [...] /proc/123/fd/1 -> /dev/pts/2
    l-wx------ 1 [...] /proc/123/fd/1 -> pipe:[12345]
    $ ./test.sh | cat
    l-wx------ 1 [...] /proc/124/fd/1 -> pipe:[12346]
    l-wx------ 1 [...] /proc/124/fd/1 -> pipe:[12347]
  • 1
    And ./test.sh > HERE? Apr 26, 2023 at 17:29
  • @ArkadiuszDrabczyk that is handled by [ -f ]... so... if [ -p "/proc/$$/fd/1" ] || [ if -p "/proc/$$/fd/1" ] will handle both pipes (script | tee) and redirects to normal files (script > foo) May 10, 2023 at 15:54

You must log in to answer this question.

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