No Linux, como posso testar se a saída de um programa está indo para um terminal ativo ou para um arquivo?

StackOverflow https://stackoverflow.com/questions/2142796

Pergunta

Quando você usa idiota parece saber magicamente se a saída padrão está passando por um canal ou em um arquivo versus quando está sendo exibida no console.Por exemplo, se você tiver as cores ativadas e não

git status

ele colorirá a saída para diferentes categorias de arquivos listados.No entanto, se você fizer

git status | less

ou

git status > status.txt

ele remove o formatação de cores linux e você verá apenas texto simples e sem cor.

Como é que git detectar se a saída de seus comandos vai para o arquivo ou para o terminal?

Foi útil?

Solução

isatty(int fd) verificará se o FD se refere a um terminal ou a outra coisa. Faz parte de unistd.h na biblioteca GNU C.

Página do homem: http://linux.die.net/man/3/isatty

Como um aparte: se você quiser ler de um programa usando outro programa, mas você quer enganar isatty Pensando que seu programa é humano, há uma maneira de fazer isso. Você pode usar um pseudo-terminal (Pty). Esta técnica é usada por Espero, por exemplo.

Outras dicas

Este é um código C para demonstrar como detectar se a saída padrão é redirecionada:

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... */
}

É assim que o Git sabe se a saída está indo para o terminal ou para um arquivo.

Posso confirmar que é disso que o git depende:

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

Execute na árvore de origem do git.

Observe que fds 0=stdin, 1=stdout, 2=stderr por padrão, mas é claro que eles podem ser redirecionados ou fechados (normalmente, se você for um daemon, feche seus descritores de arquivo e reabra os que deseja).

De um script de shell, use o -t Sinalizador de teste aplicado ao descritor de arquivo 0 (entrada padrão).

Exemplos:

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

# Modern interactive shells: ksh, bash, zsh
[[ -t 0 ]] && echo This is a terminal
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top