1

I have a bash script that columnizes a list of items. By default it will guess at the number of columns to output, based on the terminal width as reported by stty size. But when the script is in a pipeline, stty reports "Inappropriate ioctl for device".

What I want is to allow my script, when being executed as a command in the middle of a pipeline, to discover whether the pipeline it's part of is ultimately outputting to a tty - and if so, be able to stty its characteristics.

SOLUTION: As pointed out below, stty -F /dev/tty seems to work anywhere in a pipeline.

5
  • tty or tty -s will tell you if you are connected to a tty, wheter explicitly (tty) or by return code (tty -s). I suspect that in middle of ` foo | myshell | bar ` that might not work, but you cna give a try.
    – Archemar
    Mar 23, 2015 at 10:33
  • maybe your script is not run in a pipeline ... so this question lacks context
    – Skaperen
    Mar 23, 2015 at 11:10
  • Your term "tty context" is misleading. Even in the case of pipelines (as Stephen showed in his answer) your processes are attached to a tty (if not detached from the terminal). From any of the processes you can (for example) still output to /dev/tty. I suggest to rephrase your question in that respect.
    – Janis
    Mar 23, 2015 at 15:10
  • RashaMatt, I had been objecting against your term "tty context". But you changed it meanwhile. Fine. WRT your comment; I don't understand what you mean by 'its "width"'.
    – Janis
    Mar 24, 2015 at 0:34
  • @Janis, console width, as returned by stty size. Console width is required in order to intelligently guess at how to columnize output, e.g. as is done by ls.
    – RashaMatt
    Mar 24, 2015 at 1:24

1 Answer 1

6

You can try things out with a script such as

#!/bin/sh

for fd in 0 1 2; do
    if [ -t $fd ]; then echo $fd is a TTY; fi
done

Running this I see that:

  • if the script is run on its own, all three FDs are TTYs
  • if the script is run at the start of a pipeline, stdin and stderr are TTYs
  • if the script is run in the middle of a pipeline, stderr is a TTY
  • if the script is run at the end of a pipeline, stdout and stderr are TTYs

That all seems logical. Obviously if the pipeline redirects stderr as well the behaviour will be different.

To answer your question in full, I don't think it's possible to determine the terminal characteristics in all cases, but if you can find a FD (examine all the entries in /dev/fd) that's a TTY, you can run stty on that... But it isn't possible from the middle of a pipeline to determine where the end of the pipeline is going.

As mentioned by Janis, if you want to find out information about the controlling terminal, regardless of the pipeline, you can use /dev/tty, e.g. with stty -F /dev/tty; but that will fail if the script is run without a controlling terminal, e.g. from a cron job.

3
  • Thanks - this is a solution when the script is either the first (stdin works) or the last (stdout works) command in the pipeline. But when the script is nether first nor last, stty fails for file handles 0-2.
    – RashaMatt
    Mar 23, 2015 at 23:52
  • OK, it looks like stty -F /dev/tty succeeds at any point in the pipeline. Thanks!
    – RashaMatt
    Mar 24, 2015 at 1:40
  • 1
    That only works if there is a controlling TTY; so for example if your script is ever run in a cronjob it will fail. Mar 24, 2015 at 5:37

You must log in to answer this question.

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