5

Up until recently I was under the impression that Unix-y programs were unaware of where their output went, be it to standard out, redirected to a file, or into a pipe. However, an unrelated U&L question on this site brought to my attention the following example:

% echo "hello world" > file

% grep --color=auto lo file
hello world

% grep --color=auto lo file | cat
hello world

Obviously you can't see it here, but the first command shows 'lo' highlighted, as expected. However, the second call, which goes through a pipe, shows no colour. This suggests that grep was aware of its output being directed to a pipe and avoided outputting colour. How is this done?

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
noffle
  • 1,140
  • 1
  • 10
  • 18
  • 1
    See [ls command operating differently depending on recipient](http://unix.stackexchange.com/questions/22162/ls-command-operating-differently-depending-on-recipient) for a similar discussion. – manatwork Mar 23 '12 at 14:51
  • 1
    The key is that classic command-line oriented unix programs *can* operate without knowing or caring what their stdin and stdout filehandles refer to, not that they must remain unaware. Besides color, tools like `ls` and `grep` will also treat whitespace differently if they think they're talking to a 2-dimensional console rather than a 1-dimensional file stream. – Russell Borogove Mar 23 '12 at 17:42

3 Answers3

11

It is possible to determine whether a file descriptor refers to a tty.

Check out the isatty function.

Alternatively, you can use the fstat function which gives you a chunk of information on the file.

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
jakob
  • 386
  • 2
  • 4
2

Yes, they are. There are several methods to determine where the output is going. For a comparison see my answer to a related question on stackoverflow.

maxschlepzig
  • 56,316
  • 50
  • 205
  • 279
0

Easily. Different ways can be used to determine where the output is going. So in python you could do something like

    /* CODE. Input will be parsed and executed */
int
PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit,
                     PyCompilerFlags *flags)
       {
    if (filename == NULL)
        filename = "???";
    if (Py_FdIsInteractive(fp, filename)) {
        int err = PyRun_InteractiveLoopFlags(fp, filename, flags);
noffle
  • 1,140
  • 1
  • 10
  • 18