¿Cuál es la diferencia entre STDIN y los argumentos pasados ​​al comando?

16

Podría usar cualquiera de los dos formularios para ejecutar el catmétodo:

cat file_name
cat < file_name

El resultado es el mismo

Entonces quiero ejecutar manen el formato destdin

man < file_name

Mientras file_namecontiene:

# file_name
cat

Pero aparece en What manual page do you want?lugar de ejecutar man cat.

Quiero saber por qué catpodría aceptar stdincomo argumentos pero manno puedo. ¿Y cuál es la diferencia entre argumentos de línea de comando y stdin?

steveyang
fuente

Respuestas:

21

Su pregunta está estrechamente relacionada con cómo el shell que está utilizando analiza la entrada del usuario en la línea de comando.

Si la primera palabra en la línea de comando es un programa, ubicado en una carpeta especial (en su mayoría definida por PATH) y no se dan más caracteres especiales (depende del shell que esté usando), todas las palabras posteriores separadas por espacios o pestañas se pasan a el programa en una forma especial, es decir, una matriz. Con cada palabra como un elemento en la matriz.

La forma en que el programa que va a invocar interpreta los argumentos (ubicados en la matriz) depende de cómo esté programado. Existen algunos estándares cuasi de cómo debería ser la sintaxis de los argumentos, pero en general el programador es completamente libre. Por lo tanto, el primer argumento puede interpretarse como el nombre de un archivo o lo que sea que el programador haya pensado en el momento en que escribió el programa.

En el caso de agregar el carácter especial <o >con la línea de comandos, los comandos -a cáscara dosn't <y >ni palabras posteriores a la matriz que se pasa al programa. Con <o >dado, el shell comienza a hacer cosas elegantes, respaldadas por el núcleo subyacente ( canalización de palabras clave ). Para comprender lo que está sucediendo, debe comprender qué son STDINy STDOUT(dado que no está inmediatamente relacionado, lo omito STDERR).

Todo lo visible que ve en su terminal (en la mayoría de los casos, una parte de su pantalla) está escrito por el shell o cualquier otro programa que haya invocado previamente a un archivo especial (en Unix todo es un archivo ). Este archivo tiene una identificación especial y se llama STDOUT. Si un programa quiere leer datos del teclado, no sondea el teclado directamente (al menos en la mayoría de los casos) sino que lee desde un archivo especial llamado STDIN. Internamente, este archivo está conectado a su dispositivo de entrada estándar, su teclado en la mayoría de los casos.

Si el shell lee <o >en una línea de comando analizada, manipula STDINo STDOUTde un tipo particular durante el tiempo que se ejecuta el programa correspondiente. STDINy dos ya STDOUTno apuntan a la terminal o al dispositivo de entrada estándar, sino al nombre de archivo posterior en la línea de comando.

En el caso de las dos líneas

cat file_name
cat < file_name

el comportamiento observado es idéntico porque el desarrollador correspondiente hace catleer STDINo leer los datos del archivo, cuyo nombre se da como el primer argumento de línea de comando (que es el primer elemento en la matriz a la que pasa el shell cat). Posteriormente catescribe todo el contenido de file_nameo STDINen la terminal ya que no le indicamos al shell que manipule STDOUT. Recuerde que en la segunda línea su shell manipula STDINde esta manera, que ya no apunta a su dispositivo de entrada estándar sino que apunta a un archivo llamado file_nameen su directorio de trabajo actual.

En el otro caso de la línea

man < file_name

manno está destinado a leer nada STDINsi se llama sin argumento, es decir, una matriz vacía. Entonces la linea

man < file_name

es igual

man

Por ejemplo, mantambién leerá algo STDINsi pasa -l -a man. Con esta opción en la línea de comando, puede mostrar el contenido de cualquier cosa que se manlea STDINen su terminal. Entonces

man -l - < file_name

también funcionaría (pero tenga cuidado, manno solo es un buscapersonas, sino que también analiza la entrada del archivo y, por lo tanto, el contenido del archivo y el contenido mostrado podrían diferir).

Entonces STDIN, cómo STDOUTy los argumentos de la línea de comandos son interpretados, todo depende del desarrollador correspondiente.

Espero que mi respuesta pueda aclarar las cosas.

usuario1146332
fuente
Gracias por esta explicación detallada. En sus últimos párrafos, mencionó el uso man -l - < file_namepara hacer maninterpretaciones STDINcomo argumentos, pero falla en mi sistema con STDERR:man -l - < tee man: invalid option -- l man, version 1.6c
steveyang
De nada. Pero no mencioné que al menos mi versión de man( man-db ) lee argumentos STDINcon los argumentos dados -lseguidos de -. Simplemente interpreta los datos STDINcomo una página de manual. Para obtener explicaciones más detalladas de los argumentos válidos y cómo se interpretan, debe consultar la página del manual del programa relacionado. En su caso consultar man man. Tal vez hay una opción similar para su man. Si desea leer los argumentos de la línea de comandos para un programa específico STDIN xargs(como se mencionó anteriormente), este es el camino a seguir.
user1146332
Yo man many encontrar el que está en mi sistema operativo no lo admite. De todos modos, gracias por esta declaración de estos dos conceptos para mí.
steveyang
Edité su respuesta para que contenga enlaces realmente útiles en lugar de lmgtfy. Publicar enlaces de lmgtfy es 1) grosero, 2) poco útil y 3) realmente mal visto en los sitios de SE. Proporcione un enlace o no, pero si elige hacerlo, proporcione un enlace a la información real y no a una forma sarcástica de mostrarle a alguien cómo encontrarlo.
terdon
12

Son completamente diferentes. Los argumentos de la línea de comandos se pasan al programa en una matriz y puede hacer lo que quiera con ellos; stdin es un flujo de entrada del que el programa debe solicitar datos Los programas que procesan archivos a menudo eligen admitir ambos, pero tienen que hacerlo manualmente: comprueban si se pasó un nombre de archivo como argumento de línea de comando y, si no, leen de stdin.

Parece que espera manleer stdin para encontrar la página de manual que debería mostrar, lo cual sería un comportamiento realmente extraño; ¿Cuándo usarías eso? El hecho de que catmuestre su stdin es un hecho del hecho de que no hace nada más; No creo que ninguna otra herramienta funcione de esa manera. Por ejemplo, greppuede tomar un nombre de archivo o leer stdin, pero procesa los datos stdin, no lee un nombre de archivo stdiny luego lo abre

Si realmente necesita este comportamiento, puede usarlo xargs, que convierte un archivo en argumentos de línea de comandos:

$ xargs man < file_name

O simplemente inserte una catllamada dentro de la manllamada:

$ man $(cat file_name)
Michael Mrozek
fuente
En bash, puedes usar man $(<file_name).
jordanm
Re: "No creo que ninguna otra herramienta funcione de esa manera" - Perl's (<>)en un bucle servirá STDINo los argumentos de la línea de comandos como nombres de archivo ...
Aaron D. Marasco
@ AaronD.Marasco Quise decir que ninguna herramienta toma un argumento o lee un nombre de archivo de stdin y lee el argumento de ese archivo
Michael Mrozek
@MichaelMrozek Gracias por esta aclaración. El propósito que utilicé man < file_namees ayudarme a comprender estos dos conceptos. Leyendo su explicación, la implementación la decide el autor del comando. Entonces, si estoy debajo de la derecha, la findtoma de argumentos procesa STDIN
steveyang