Dizer se um descritor de arquivo aponta para um dispositivo terminal
Um programa pode saber se um descritor de arquivo está associado a um dispositivo tty usando a isatty()função C padrão (que geralmente ocorre por baixo de uma ioctl()chamada inócua ao sistema específica de tty que retornaria com um erro quando o fd não aponta para um dispositivo tty) .
o [test utilitário / pode fazer isso com seu -toperador.
if [ -t 1 ]; then
echo stdout is open to a terminal
fi
Rastreando chamadas da função libc em um sistema GNU / Linux:
$ ltrace [ -t 1 ] | cat
[...]
isatty(1) = 0
[...]
Rastreando chamadas do sistema:
$ strace [ -t 1 ] | cat
[...]
ioctl(1, TCGETS, 0x7fffd9fb3010) = -1 ENOTTY (Inappropriate ioctl for device)
[...]
Dizer se aponta para um tubo
Para determinar se um fd está associado a um pipe / fifo, pode-se usar a fstat()chamada do sistema , que retorna uma estrutura cujo st_modecampo contém o tipo e as permissões do arquivo aberto nesse fd. oS_ISFIFO() macro C padrão pode ser usada nesse st_modecampo para determinar se o fd é um pipe / fifo.
Não existe um utilitário padrão que possa fazer um fstat(), mas existem várias implementações incompatíveis de um statcomando que podem fazê-lo. zsh's statbuiltin com o stat -sf "$fd" +modequal retorna o modo como uma representação de string cujo primeiro caractere representa o tipo ( ppara pipe). O GNU statpode fazer o mesmo com stat -c %A - <&"$fd", mas também precisa stat -c %F - <&"$fd"reportar o tipo sozinho. Com BSDstat : stat -f %St <&"$fd"ou stat -f %HT <&"$fd".
Dizer se é procurável
Os aplicativos geralmente não se importam se o stdout é um pipe. Eles podem se importar com a possibilidade de procurar (embora geralmente não decida se o buffer deve ou não).
Para testar se um fd é procurável (tubos, soquetes, dispositivos tty não são procuráveis, arquivos regulares e a maioria dos dispositivos de bloco geralmente são), pode-se tentar uma lseek()chamada de sistema relativa com um deslocamento de 0 (tão inócuo). ddé um utilitário padrão que é uma interface paralseek() mas não pode ser usado para esse teste, pois as implementações não seriam necessárias lseek()se você solicitasse um deslocamento de 0.
No entanto, os shells zshe ksh93builtin procuram operadores:
$ strace -e lseek ksh -c ': 1>#((CUR))' | cat
lseek(1, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek)
ksh: 1: not seekable
$ strace -e lseek zsh -c 'zmodload zsh/system; sysseek -w current -u 1 0 || syserror'
lseek(1, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek)
Illegal seek
Desativando o buffer
o script comando usa um par de pseudo-terminais para capturar a saída de um programa, portanto, o stdout do programa (e stdin e stderr) será um dispositivo de pseudo-terminal.
Quando o stdout é para um dispositivo terminal, geralmente ainda existe algum buffer, mas é baseado em linha. printf/puts e co não escreverá nada até que um caractere de nova linha seja produzido. Para outros tipos de arquivos, o buffer é em blocos (de alguns quilos).
Existem várias opções para desativar o buffer que são discutidas em várias perguntas e respostas aqui (pesquise unbuffer ou stdbuf , Não é possível redirecionar a saída de corte fornece algumas abordagens) usando um pseudo-terminal, como pode ser feito por socat/ script/ expect/ unbuffer(um expectscript) / zsh's zptyou injetando código no executável para desativar o buffer conforme feito pelo GNU ou FreeBSD stdbuf.