Comprender cómo se envían las entradas a las tuberías en Bash

17

No entiendo cómo funcionan las tuberías en bash.

Sé que toma una salida de un comando como entrada en otro comando.

Lo que puedo obtener es una salida porque es lo que el comando imprime en la pantalla.

Pero, ¿cómo sé qué entrada tomará un comando?

Aquí hay un ejemplo que pensé que funcionaría:

which gem | rm

Lamentablemente no fue así.

¿Qué gema se imprime /usr/bin/gemasí que esa debe ser la salida correcta?

Pensé que se le había dado a rm así que sería, rm /usr/bin/gempero me equivoqué.

Entonces mi pregunta es, ¿cómo sé qué entrada toma un comando?

ajsie
fuente
2
Aparte de cualquier otra cosa, rm /usr/bin/gemes una idea terrible . Deje eso gem(y el intérprete de Ruby con el que va) solo e instale su intérprete de Ruby preferido (y gem) usando rvm: rvm.beginrescueend.com
Telemachus

Respuestas:

23

"Entrada" y "argumentos de línea de comando" son cosas diferentes.

rm elimina los archivos proporcionados como argumentos.

Una tubería redirige la salida del comando de la izquierda a la entrada del comando de la derecha. No afecta los argumentos de la línea de comandos del programa de la derecha.

Para hacer lo que intenta hacer, intente usar xargspara convertir la entrada estándar en argumentos de línea de comandos para ejecutar un programa. Ese es su trabajo.

which gem | xargs rm, por ejemplo, eliminará el gemen su RUTA.

Borealid
fuente
12

rmno toma entrada, toma argumentos. Estos son diferentes Los argumentos son los modificadores y los nombres de archivo, etc., que le da a un programa en la línea de comando para afectar su comportamiento. La entrada son los datos en los que trabaja el programa. Por ejemplo, greptoma entradas y argumentos:

grep "foo" file.txt

Hay dos argumentos allí "foo"y file.txt. La entrada es el contenido de file.txt, no la cadena en file.txtsí. Dado que grep toma entrada, puede usarla con tuberías:

cat file.txt | grep "foo"

produce la misma salida, ya que cat toma file.txtcomo argumento y produce el contenido de file.txtcomo salida. Esa salida se canaliza a grep, dando el mismo efecto que grep al abrir el archivo, como en el primer ejemplo.

Si desea utilizar la salida de un programa como argumento para otro, utilice las teclas de retroceso:

rm `which gem`

o esta sintaxis alternativa (específica de bash):

rm $(which gem)

Editar: o xargscomo señala otro respondedor. Muchas formas de pelar un gato con una línea de comando.

Tyler McHenry
fuente
Vale la pena señalar que cat file.txt | grep "foo"puede ser cientos de veces más lento que grep "foo" file.txt.
Borealid
1
Esta es la parte que no entiendo. ¿Cómo sé qué es un argumento y qué es la entrada estándar?
ajsie
8
@ajsie: Si lo escribe después del nombre del programa y antes de presionar enter, es un argumento. Si lo escribe en el programa después de que comience a ejecutarse, es una entrada estándar.
Borealid
1
¡Entendido! Esto lo explicó todo. Ahora sé que puedo usar el comando directamente y ver si me lo solicita (grep) y también podría leer el manual (man grep) para ver si usa la entrada estándar.
ajsie
@ajsie: Si no quieres sumergirte en la página de manual, también hay grep --helpuna descripción rápida de los argumentos aceptados.
Borealid
3

Consulte las manpáginas de comandos que le interesan. Estos programas le indicarán que leyeron stdin(intente man grepcon un comando popular que lea stdin).

el dedal
fuente
Lo intenté man grep | grep 'standard input'y obtuve If no file arguments are specified, the standard input is used.el último partido. 👍 Tuve que grepprobar un poco su propia medicina. 😎
ma11hew28
2

Todos estos son peligrosos de ejecutar si tiene un directorio en su RUTA que contiene espacio o si el nombre del comando contiene espacio:

rm `which gem`       # Dangerous
rm $(which gem)      # Dangerous
which gem | xargs rm # Dangerous

GNU Parallel http: // www.gnu.org/software/parallel/ no tiene ese problema, por lo que esto funcionará incluso si tiene un directorio en su RUTA que contiene espacio o si el nombre del comando contiene espacio:

which gem | parallel rm
parallel -a <(which bass) rm

Mire el video de introducción de GNU Parallel: http://www.youtube.com/watch?v=OpaiGYxkSuQ

Ole Tange
fuente