¿Qué hace el símbolo de tubería de Linux "|"? [duplicar]

23

Aquí hay un comando que ordena los archivos en una carpeta en orden inverso

ls | sort -r

¿Qué hace el |símbolo en ese comando?

Lo que realmente estoy buscando aquí es una explicación de alto nivel (fácil de entender) de tuberías para principiantes de Linux. Veo otras preguntas sobre tuberías aquí en Superusuario, pero nada que genere una respuesta que explique en términos simples lo que hacen y en qué se diferencian de la redirección (el símbolo >o <).

ccalvert
fuente
77
Esto no tiene nada que ver con Linux (que es un núcleo). Las tuberías en general son un medio de redirigir la entrada / salida, en un shell como bash no es diferente. Lo único especial de a |es que no utiliza un nombre, la salida del comando l-hand se pasa directamente a la entrada para el comando en el lado de la mano derecha de la tubería.
Andon M. Coleman
Para una lección de historia sobre el tema, lea linfo.org/pipe.html
Fredrik Pihl
ls -1r(Tenga en cuenta el argumento número uno) debería producir un resultado similar a ls | sort -r.
Ivan Chau
Me gusta explicarlo de esa manera: una tubería toma la salida de un comando y la hace utilizable para el siguiente comando. Por ejemplo, puedes hacer cat /somefile | grep cool. Esto tomará la salida de algún archivo y lo pondrá a disposición para grep, y luego grep imprimirá todas las líneas con la palabra cool.
JohnDoea

Respuestas:

26

Lo siguiente se simplifica un poco para ayudar a los nuevos usuarios.

Bueno, primero, es necesario comprender el concepto de entrada estándar y salida estándar.

En Linux y otros sistemas operativos similares a UNIX, cada proceso tiene una entrada estándar ( stdin) y una salida estándar ( stdout). La situación habitual es que stdines su teclado y stdoutes su pantalla o ventana de terminal.

Entonces, cuando corres ls, arrojará su salida a stdout. Si no hace nada más, irá a su pantalla o ventana de terminal, y lo verá.

Ahora, algunos comandos de Linux interactúan con el usuario y lo stdinhacen, siendo su editor de texto uno de esos. Se lee stdinpara aceptar las pulsaciones del teclado, hacer cosas y luego escribe cosas stdout.

Sin embargo, también hay comandos no interactivos o de "filtro" que NO funcionan de manera interactiva, pero quieren un montón de datos. Estos comandos tomarán todo lo que stdintenga, le harán algo y luego lo lanzarán astdout

Veamos otro comando llamado du: representa el uso del disco. du /usr, por ejemplo, imprimirá (para stdoutgustarle cualquier otro comando de Linux) una lista de cada archivo en ese directorio y su tamaño:

# du /usr
2312    /usr/games
124     /usr/lib/tc
692     /usr/lib/rygel-1.0
400     /usr/lib/apt/methods
40      /usr/lib/apt/solvers
444     /usr/lib/apt
6772    /usr/lib/gnash

Como se puede ver de inmediato, no está ordenado, y probablemente desee ordenarlo por orden de tamaño.

sortes uno de esos comandos de "filtro" que tomará un montón de cosas stdiny las ordenará.

Entonces, si hacemos esto:

# du /usr | sort -nr

obtenemos esto, que es un poco mejor:

4213348 /usr
2070308 /usr/lib
1747764 /usr/share
583668  /usr/lib/vmware
501700  /usr/share/locale
366476  /usr/lib/x86_64-linux-gnu
318660  /usr/lib/libreoffice
295388  /usr/lib/vmware/modules
290376  /usr/lib/vmware/modules/binary
279056  /usr/lib/libreoffice/program
216980  /usr/share/icons

Y ahora puede ver que la "tubería" conecta el stdoutcomando de uno al stdinotro. Por lo general, lo usará en situaciones como esta en las que desea filtrar, ordenar o manipular la salida de un comando. Se pueden conectar en cascada si desea procesar la salida a través de múltiples comandos de tipo filtro.

Si escribe sortsolo, aún intentará leer stdin. Como stdinestá conectado a su teclado, esperará a que escriba y procese las cosas hasta que presione Control-D. No le avisará, ya que no está destinado a ser utilizado de forma interactiva.

Es posible que un programa sepa si stdines interactivo o no, por lo que algunos programas pueden actuar de manera diferente si los emite por sí mismos o al final de una tubería.

Además, canalizar un programa que solo funciona de forma interactiva, por ejemplo vi, te hará pasar un mal momento.

Las canalizaciones son diferentes de la redirección en que los datos se barajan de un comando a otro sin almacenarse en ningún lado. Entonces, en el ejemplo anterior, dula salida de 'no se almacena en ningún lado. La mayoría de las veces no quiere esto con tuberías porque la razón para usar tuberías es procesar la salida de un comando de alguna manera, pero hay un comando teeque le permite tener su pastel y comérselo también, lo hará copie lo que recibe de stdinambos stdouty un archivo de su elección. También es probable que pueda hacer esto bashcon alguna sintaxis arcana que implique símbolos y corchetes que no conozco.

LawrenceC
fuente
Tenga en cuenta que esto no es exclusivo de Linux, o incluso POSIX. La mayoría de los shells en Windows también hacen esto. Y probablemente otros sistemas operativos.
Bob
Conozco el concepto stdiny stdoutes diferente en Windows que en Linux, aunque probablemente no desde el punto de vista de Windows cmd.exeo Powershell.
LawrenceC
Tengo curiosidad sobre cómo es diferente, ¿te importaría explicarlo? Tal vez en el chat si los comentarios no son un buen lugar para ello.
Bob
1
Los programas Win32 definitivamente tienen una entrada y salida estándar. Por ejemplo, puede recuperar la entrada estándar, la salida o el identificador de error de su proceso con la función Win32 GetStdHandle(). También es trivial redirigir las secuencias estándar de un proceso [secundario] generado con .NET, que creo que se asigna a las funciones de Win32 (pero no estoy 100% seguro de eso, no soy un desarrollador de Win32).
Bob
1
Ah, aquí está el equivalente de Win32, estableciendo los parámetros apropiados en la STARTUPINFOestructura para CreateProcess().
Bob
27

Si se siente cómodo con la redirección de salida y entrada, la explicación es realmente bastante fácil.

Command1 | Command2

hace lo mismo que

Command1 > tempfile
Command2 < tempfile

pero sin tempfile. La salida de Command1está directamente conectada a la entrada de Command2y la transferencia ocurre en la memoria.

Daniel B
fuente
Podría estar equivocado, pero creo que el archivo temporal existe incluso en la sintaxis de la tubería. Simplemente no tiene nombre.
Taemyr
3
No, no lo hace. No se involucran operaciones del sistema de archivos al canalizar la salida de un comando a la entrada de otro comando.
Daniel B
1
Sin embargo, bajo DOS (y lo más probable Windows), un archivo temporal se crea por la tubería. No * nix, pero nada vale la diferencia.
Jeremy J Starcher
Estoy bastante seguro de que esto no es correcto. Process Monitor informa que no CreateFileo WriteFilellama para respaldar su reclamo. / edit: Eso es para la parte de Windows, por supuesto.
Daniel B
3

Realmente, si quieres saber qué hacen las canalizaciones y la diferencia entre> y |, ve a un directorio con muchos archivos y

desde una terminal ls vs ls | more (o haciendo eso desde Windows con DIR y DIR | MÁS)

Si usó> más, verá que crea un archivo llamado 'más' en lugar de enviar la salida de ls al comando 'más'. Entonces, si alguien hiciera> más, probablemente sería un error, uno no haría> más que haría> file1. Más es un comando bien conocido.

El <like the> también sirve para vincular un comando y un archivo, en lugar de un comando a un comando. Pero mientras> envía la salida de un comando a un archivo, el <envía un archivo como entrada a un comando. Raramente uso <como suelo usar cat file1 | para enviar la salida de un archivo a un comando.

$ grep a <archivo1 abc

$ cat archivo1 | grep a abc

grep con 2 parámetros tiene el formato de archivo de patrón grep. grep con un parámetro es el patrón grep. Y puede enviarle el archivo canalizando el contenido del archivo o usando <. Si usa <, primero escribe el nombre del comando, luego el nombre del archivo después del comando <archivo. Si usa | para canalizar el contenido de un archivo, usa cat file1 | mando.

Además, muchos comandos toman un archivo como entrada de todos modos, por lo que grep un archivo1 funcionará, al igual que cat file1 | grep a, y grep a <archivo1.

Estaba haciendo canalizaciones (|) y> en DOS incluso hace 15 años.

Para resumir cómo | difiere de <y> - La tubería se encuentra entre 2 comandos El <y> se sienta entre un comando y un archivo. El> se emite a un archivo. El <se ingresa desde un archivo.

barlop
fuente
3

El carácter de canalización ( |) conecta la salida de un programa a la entrada de otro.

En este ejemplo echoimprime la palabra helloy wc -chace un recuento de caracteres de su entrada:

echo hello | wc -c
bbaassssiiee
fuente
Creo que deberías decir de inmediato que echo generará "hola \ n". No le está diciendo al OP que estudie, se lo está diciendo a todos los que leen su respuesta. ¿Por qué multiplicar esta pérdida de tiempo?
Rodrigo
Gracias por los comentarios, acorté mi respuesta.
bbaassssiiee
2

Para entender esto, pruébalo tú mismo:

sort -r

Ahora estás colgando con un cursor, y no está haciendo nada. ¿Qué sucede si escribes algunos datos?

1
2
3
5
4

Todavía nada, ¿verdad? Ahora presiona ctrl + D

5
4
3
2
1

Entonces, lo que hace es tomar entrada (lo que escribió), hace algo con ella (ordena) y la devuelve como salida. El lscomando no toma entrada, solo genera salida. El símbolo de tubería toma la salida lsy la alimenta como entrada al sortcomando.

>no alimenta la salida a un programa, pero almacena la salida como un archivo. <usa un archivo como entrada.

jornane
fuente