menos archivo1 archivo2 | gato: ¿por qué funciona?


21

Cuando utilizo less file1 file2, obtengo los dos archivos que se muestran en el "visor de menos búfer", pero less file1 file2 | catimprime el contenido de ambos archivos adjuntos a stdout. ¿Cómo sabe menos si debería mostrar el "visor de menos búfer" o producir resultados en stdout para un próximo comando? ¿Qué mecanismo se usa para hacer esto?

Respuestas:


30

lessImprime el texto en stdout. stdout va

  • a un terminal (/ dev / tty?) y abre el visor de búfer predeterminado
  • a través de una tubería al conectarlo a otro programa usando | ( less text | cut -d: -f1)
  • a un archivo al redirigirlo con> ( less text > tmp)

Hay una función C llamada "isa tty " que comprueba si la salida va a un tty (menos 4.81, main.c, línea 112). Si es así, utiliza el visor de búfer, de lo contrario se comporta como cat.

En bash puedes usar test (ver man test)

  • -t FD descriptor de archivo FD se abre en un terminal
  • -p ARCHIVO existe y es una tubería con nombre

Ejemplo:

[[ -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'

1
@tfh Si STDOUT no está conectado a una tubería o una redirección, es correcto que no impriman que STDOUT está conectado a una tubería o una redirección. Pon los tres en un guión. Llamada bash script.sh, bash script.sh | cat, bash script.sh > file, y ver lo que la producción que se obtiene.
hvd

1
stdoutno es algo que se pueda "escribir en un archivo". Es algo que debes write() hacer . lessno tiene que hacer nada diferente dependiendo de si su salida es un archivo, tubería, socket o dispositivo de bloque, o lo que sea. Solo importa que no sea un tty, por lo que simplemente se comporta como cat. (Supongo que lo sabías y elegiste las palabras incorrectas para explicarlo, pero pensé en señalarlo a otros lectores).
Peter Cordes

Entonces, quiere decir que es tarea de menos comportarse como un gato en mi pregunta específica, o más general: comportarse como el siguiente comando en una tubería. Por lo que entendí, no puedo suponer que el mismo comportamiento exacto se implemente también en una herramienta diferente.
tfh

@ tfh: No, lessno se "da cuenta" de lo que catsigue. Simplemente se comporta como catsi fuera lo siguiente, si es stdout no es un tty.
Peter Cordes

@MichaelD .: gracias, corrigió mi respuesta. Supuse que lessseguiría adelante y usaría un TCGETS para obtener las dimensiones de la terminal o descubriría que no es un tty, pero aparentemente adiviné mal.
Peter Cordes

6

lesscomprueba si stdoutes un terminal y se comporta como catcuando no lo es (copia stdin en stdout hasta EOF).

Esta característica le permite escribir secuencias de comandos o programas que siempre envían su salida (por ejemplo, --helpsalida) a la lessvez que permite una fácil redirección a un archivo. Sería un asco si some_command --fullhelp > help.txttodavía esperara la barra espaciadora en stdin para paginar el texto, o algo así. Algunos comandos (por ejemplo man) verifican que su propia salida decida si enviar su salida a través de un localizador o no. Si corres man ls > ls.txt, nunca invoca tu $PAGER.

lessEl comportamiento de gato es útil si olvida editarlo de una sola línea al agregar más etapas a una tubería también.


lessnecesita averiguar las dimensiones del terminal (tamaño de la pantalla, para saber cuántas líneas mostrar a la vez). El ioctl(2)que usa stdoutdevolvería ENOTTY en un no terminal, por lo que no puede evitar manejar el caso no terminal de todos modos. lessen realidad se usa isatty(3)antes de verificar las dimensiones del terminal, pero isattyfunciona probando un ioctl solo tty y verificando la falta de error.

Incluso un buscapersonas simple como more(1)(al menos la versión util-linux) tiene esta característica, porque probablemente sea el comportamiento sensato más simple de implementar para ese caso.


Tenga en cuenta que cuando algo tubería en less (por ejemplo grep foo bar.txt | less), se tiene que abrir /dev/ttypara la entrada de teclado. (Puedes verlo hacer esto con echo foo | strace less).

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.