less file1 file2 | gato - por que funciona?

20

Quando eu utilizo less file1 file2 , recebo os dois arquivos mostrados em "menos visualizador de buffer", mas less file1 file2 | cat imprime o conteúdo de ambos os arquivos anexados ao stdout. Como é que menos sabe se deve mostrar o "menos visualizador de buffer" ou produzir saída para stdout para um próximo comando? Qual mecanismo é usado para fazer isso?

    
por tfh 30.12.2016 / 11:54

2 respostas

29

less imprime o texto na stdout. stdout vai

  • para um terminal (/ dev / tty?) e abre o visualizador padrão de buffer
  • por meio de um pipe ao direcioná-lo para outro programa usando | ( less text | cut -d: -f1 )
  • para um arquivo ao redirecioná-lo com > ( less text > tmp )

Existe uma função C chamada "isa tty " que verifica se a saída está indo para um tty (menos 4.81, main.c, linha 112). Em caso afirmativo, ele usa o visualizador de buffer, caso contrário, ele se comporta como cat .

No bash você pode usar o teste (veja man test )

  • -t Descritor de arquivos FD FD é aberto em um terminal
  • -p FILE existe e é um pipe nomeado

Exemplo:

[[ -t 1 ]] && \
    echo 'STDOUT is attached to TTY'

[[ -p /dev/stdout ]] && \
    echo 'STDOUT is attached to a pipe'

[[ ! -t 1 && ! -p /dev/stdout ]] && \
    echo 'STDOUT is attached to a redirection'
    
por 30.12.2016 / 12:26
6

less verifica se o stdout é um terminal e se comporta como cat quando não é (copia stdin para stdout até EOF).

Esse recurso permite que você escreva scripts ou programas que sempre enviam seus resultados (por exemplo, --help output) até less , permitindo ainda o fácil redirecionamento para um arquivo. Seria uma droga se some_command --fullhelp > help.txt ainda esperasse pela barra de espaço no stdin para folhear o texto, ou algo assim. Alguns comandos (por exemplo, man ) verificam se sua própria saída decide se envia sua saída por meio de um pager ou não. Se você executar man ls > ls.txt , ele nunca chamará seu $PAGER .

O comportamento semelhante ao gato de

less é útil se você esquecer de editá-lo de uma só linha ao adicionar mais etapas a um pipeline também.

less precisa descobrir as dimensões do terminal (tamanho da tela, para saber quantas linhas mostrar de uma só vez). O ioctl(2) que ele usa em stdout retornaria ENOTTY em um terminal não-terminal , então não pode evitar manipular o case não-terminal de qualquer maneira. less usa, na verdade, isatty(3) antes de verificar as dimensões do terminal, mas isatty funciona tentando um ioctl apenas para tty e verificando a falta de erros.

Mesmo um pager simples como more(1) (pelo menos a versão util-linux) tem esse recurso, porque é provavelmente o comportamento mais simples a ser implementado para esse caso.

Observe que quando você canaliza algo para less (por exemplo, grep foo bar.txt | less ), ele precisa abrir /dev/tty para a entrada do teclado. (Você pode ver isso com echo foo | strace less ).

    
por 31.12.2016 / 05:29

Tags