In linux, how can I test whether the output of a program is going to a live terminal or to a file?
Asked Answered
P

4

9

When you use git it seems to magically know whether standard out is going through a pipe or into a file vs when it is being displayed to the console. For example, if you have colors enabled and you do

git status

it will colorize the output for different categories of files being listed. However, if you do

git status | less

or

git status > status.txt

it removes the linux color formatting and you only see plain, uncolored text.

How does git detect whether the output of its commands are going to file vs going to the terminal?

Pentastich answered 26/1, 2010 at 21:31 Comment(3)
I don't think that this should be on superuser, as the OP is really looking for is how does the program ie. git detects where it is being redirected or not.Cantle
I agree with @tommieb75 it is an API question, not a how do I admin question.Burgos
By the way, if you weren't just curious, and you were asking this because you wanted to have colorized and paged output from git, you can mess with git config settings like core.pager (less) and color.pager (true). kernel.org/pub/software/scm/git/docs/git-config.htmlSkepful
S
14

isatty(int fd) will check whether the fd refers to a terminal or something else. It's part of unistd.h in the GNU C library.

Man page: http://linux.die.net/man/3/isatty

As an aside: if you want to read from a program using another program, but you want to fool isatty into thinking that your program is a human, there is a way to do that. You can use a pseudo-terminal (pty). This technique is used by expect, for example.

Skepful answered 26/1, 2010 at 21:34 Comment(0)
C
8

This is a C Code to demonstrate how to detect if standard output is redirected:

int main(int argc, char **argv){
    if (!isatty(fileno(stdout))){
      fprintf(stdout, "argv, argc, someone is redirecting me elsewhere...\n");
      return 1;
    }
    /* rest of C code here... */
}

That is how git knows whether the output is going to the terminal or to a file.

Cantle answered 26/1, 2010 at 21:38 Comment(0)
B
3

Can confirm that's what git relies on:

$ grep -ir "isatty" ./*
./builtin-commit.c:     if (isatty(0))
./builtin-config.c:         stdout_is_tty = isatty(1);
./builtin-pack-objects.c:   progress = isatty(2);
./builtin-prune-packed.c:   int opts = isatty(2) ? VERBOSE : 0;
./builtin-revert.c: if (isatty(0))
./builtin-shortlog.c:   if (!nongit && !rev.pending.nr && isatty(0))
./builtin-unpack-objects.c: quiet = !isatty(2);
./color.c:      stdout_is_tty = isatty(1);
./compat/winansi.c: if (!isatty(fileno(stream)))
./compat/winansi.c: if (!isatty(fileno(stream)))
./pack-redundant.c: if (!isatty(0)) {
./pager.c:  if (!isatty(1))
./pager.c:  if (isatty(2))
./remote-curl.c:    options.progress = !!isatty(2);
./transport.c:  args.no_progress = args.quiet || (!transport->progress && !isatty(1));
./transport-helper.c:   int no_progress = v < 0 || (!t->progress && !isatty(1));
./wt-status.c:   * will have checked isatty on stdout).

Run against the git source tree.

Note that fds 0=stdin, 1=stdout, 2=stderr by default, but these can of course be re-directed or closed (typically if you are a daemon you close your file descriptors and re-open the ones you want).

Burgos answered 26/1, 2010 at 21:40 Comment(0)
C
3

From a shell script, use the -t test flag applied to the file descriptor 0 (standard input).

Examples:

# Any Bourne-style shell
[ -t 0 ] && echo This is a terminal

# Modern interactive shells: ksh, bash, zsh
[[ -t 0 ]] && echo This is a terminal
Concertante answered 20/5, 2013 at 20:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.