I noticed that if I type:
ls --color=auto
or
ls --color=auto | cat
ls --color=auto > >(cat)
I don't see the same output. Therefore I assume a program has an hability to know whether its STDOUT is piped to something. The question is how does it know?
I checked the ENV vars with env
and env | cat
but I get the same. The answer is somewhere else. I can't figure out where.
From this question I found that I can use isatty()
who provide this function? is it part of the shell or the kernel? By going further I see that this function is part of the POSIX standard.
Now I know I have two processes that can communicate in between them with several mechanism:
- STDIN/STDOUT/STDERR
- Exit Code
- Environment variables
- System calls
Bash and ls are both programs. Thus they can only use the listed mechanisms to exchange information.
The real question behind this is how does isatty()
get the information from bash?
Best Answer
The
--color
option is a feature of the GNUls
program. GNUls
uses theisatty()
function to test whether the process's standard output is a TTY. Part of the relevant source code can be seen here:isatty()
inspects the file descriptor passed to it to see if the file descriptor represents a TTY (terminal device). The exact way that isatty() works may vary from one system to another. Here is a Darwin implementation from Apple OSX if you're interested:When you run
ls --color=auto
, your shell (bash) launches the "ls" program using the shell's own standard input, output, and error as the stdin/out/err for the "ls" process. If you are running interactively, then your shell's stdout is probably a terminal, then ls's standard output will probably be a terminal. When ls calls isatty() to test whether its standard output is a terminal, it will probably succeed.When you run something like
ls --color=auto | cat
, your shell does three things:cat
with its standard input set to be the pipe.ls
with its standard output set to be the pipe.A pipe is not a terminal. When
ls
tests whether its standard output is a tty, the test will fail.