¿Cómo se puede pasar la entrada estándar de un programa como un argumento a otro?

17

Digamos que existe un programa, que toma dos argumentos; archivo de entrada y archivo de salida.

¿Qué pasa si no desea guardar el archivo de salida en el disco, sino más bien lo pase directamente a la stdinde otro programa. ¿Hay una manera de lograr esto?

Muchos comandos que encuentro en Linux ofrecen una opción para pasar '-' como argumento del archivo de salida, que hace lo que he especificado anteriormente. ¿Es esto porque stdinno es posible pasar el argumento de un programa como argumento? Si es así, ¿cómo lo hacemos?

Un ejemplo de cómo iba a imagen utilizando esto es:

pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" stdin(echo)

La cáscara que estoy usando es bash.

Dziugas
fuente
1
cat <file | cmd /dev/fd/0Funciona en la mayoría de las unidades.
mikeserv
No funciona para mi Probado con: cat < README.txt | cp /dev/fd/0. Decíacp: missing destination file operand after ‘/dev/fd/0’ Try 'cp --help' for more information.
Dziugas
1
program input-file /dev/stdout | another-program? También tenga en cuenta que echono lee nada de stdin.
yaegashi
1
@Dziugas, por supuesto que no, no se puede cparchivar en ninguna parte. echo 1 2 3| cp /dev/fd/0 /dev/ttyimprimirá 1 2 3. Y, por cierto, /dev/fd/[num]es más probable que funcione que /dev/std(in|out|err)en la mayoría de los casos. Consulte Portabilidad de enlaces de descriptor de archivo sobre qué puede esperar para trabajar en dónde.
mikeserv
1
Un buen programa de UNIX escribiría a la salida estándar dejándolo en manos del usuario para decidir si desean volver a dirigir a un archivo o una tubería a otro comando.
Jorge Bucaran el

Respuestas:

13

Si interviene el programa escrito a cualquier descriptor de archivo, incluso si no se puede buscar, se puede utilizar /dev/stdoutcomo archivo de salida. Este es un enlace simbólico /proc/self/fd/1en mi sistema. El descriptor de archivo 1 es stdout.

TiCPU
fuente
Esto resolvió mi consulta. Entonces, ¿no hay forma de hacerlo cuando el programa necesita buscarlo?
Dziugas
3
Si usted está tratando de evitar el acceso al disco, se puede escribir el archivo en / dev / shm /, sin embargo, si usted no quiere cualquier archivo en el sistema de archivos, a continuación, por lo que yo sé, no hay manera de buscar en un tubo. Buscar los medios de avance que tendría para amortiguar todo en la memoria hasta que llegó a ese punto en adelante, y la búsqueda hacia atrás implica tener todo en la memoria buffer.
TiCPU
pdftotextal igual que muchos (pero no todos) otras utilidades de soporte -para que así (que funcionaría incluso en sistemas que no soportan / dev / stdout, o donde / dev / stdout no funcionan como se esperaba en Linux como en la salida estándar no es un tubo). pdftotext file.pdf - | wc -c
Stéphane Chazelas
11

Desde la pdftotextpágina del manual:

Si el texto-archivo es'-', el texto se envía a la salida estándar.

Entonces, en este caso, todo lo que necesita es:

pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" -

O si lo desea tubería a este STDIN de otro programa:

pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" - | another_prog

El uso -como sustituto de un nombre de archivo es una convención que siguen muchas utilidades (incluido pdftotext) cuando queremos ingresar desde STDIN o enviar a STDOUT. Sin embargo, no todas las utilidades siguen esta convención. En ese caso, la forma idiomática para hacer esto en bash es utilizar una sustitución de proceso :

my_utility "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" >( cat )

Aquí se >( )comporta en gran medida como un archivo pasado my_utility, pero en lugar de ser un archivo real, la secuencia se canaliza al stdin del proceso contenido, es decir, cat. Entonces, aquí, el texto debería aparecer como se requiere.

El uso de catcasi siempre activa las campanas de alarma UUOC en foros como este. Sostengo que si la utilidad no es compatible -, entonces este es un uso útil de cat, aunque si hay alguna forma de hacer esta sustitución del proceso sin el cat, entonces soy todo oídos ;-).

Sin embargo, si (como dice la pregunta) el destino final de la transmisión es STDIN de otro programa, entonces catse puede eliminar:

my_utility "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" >( another_prog )
Trauma digital
fuente
2
Y permítanme dar marcha atrás una vez más: si prog2escribe a la salida estándar, es mejor que , debido a las esperas de forma para que completa (es decir, antes de que los problemas de concha al siguiente mensaje o pasa a la siguiente orden (por ejemplo, después o )), mientras que el -sin forma solo espera a que se complete. Además, después del formulario, es el estado de salida de , mientras que, en el otro, es el estado de salida de . (Usted paga su dinero y le lleva a su elección.)prog1 input_file >( cat ) | prog2prog1 input_file >( prog2 )catprog2;&&catprog1cat$?prog2$?prog1
de Scott
4

Si los soportes de concha ellos, la forma más sencilla de hacer tales manipulaciones sería el uso de sustitución de proceso : <(…)e >(…). Esto funciona de bash, zsh y ksh y posiblemente otros proyectiles. Por ejemplo:

$ sort <(printf "b\nc\na\n")
a
b
c
$ ls
foo
$ cp <(find . -name foo) bar
$ ls
bar  foo

Sin embargo, esto no ayuda en el ejemplo del estado desde pdftotextguardará en un archivo de texto. Si bien su mejor opción (aparte de la obvia de usar -) es usar /dev/stdoutsegún lo sugerido por @TiCPU, también podría usar otra función de shell. La construcción se !:Nrefiere al enésimo argumento del comando anterior. Por lo tanto, se puede hacer:

$ pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf"  out.txt
$ cat !:2
terdon
fuente
1
Si bien estoy de acuerdo en que cat <()puede ser útil en algunas situaciones, en este escenario, sin embargo, no está funcionando en absoluto. El problema (muy mal descrito por OP, debo admitir) es que pdftotexttoma dos argumentos: archivo de entrada y archivo de salida . Si falta un segundo argumento, entonces no produce nada, por cat <(pdftotext "file.pdf")lo que tampoco devolvería nada. Uno puede engañar el pdftotextcomando dando >(cat)un segundo argumento como respondió Digital Trauma, pero cat <()aquí no tiene sentido. Obviamente, en pdftotextcaso de que sea mejor usarlo -como el nombre del archivo de salida.
jimmij
1
@Scott ¿Cómo es mi respuesta un UUOC? ¿Cómo haría este proceso de sustitución sin gato? >( )hará efectiva el flujo de la tubería a cualquier proceso que está dentro - así que en realidad no necesita una catpara la salida esa corriente. Normalmente, debemos ser capaces de hacer algo así pdftotext input.pdf -, pero al parecer pdftotextno admite el -parámetro de salida directamente a la salida estándar en lugar de un archivo - probarlo.
Trauma digital
1
@DigitalTrauma no es uuoc. Creo que cat es lo más rápido que puede obtener en caso de imprimir, pero de hecho puede usar otro comando >(grep something)para ser más útil. Por cierto, mi pdftotext 3.04 tareas de apoyo -como un archivo de salida, así que estoy un poco sorprendido por toda la discusión.
jimmij
1
@terdon Odio ser un fanático, pero esto no parece funcionar. Específicamente, no es diferente a la ejecución pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf", que coloca la salida en un archivo llamado C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.txt, pero nada del texto se envía a STDOUT para canalizarlo a otro programa.
Trauma digital
1
¡@DigitalTrauma que no está siendo un fanático! Ese soy yo siendo un idiota. Gracias por señalarlo y nunca te disculpes al señalar errores. Preferiría que me señalaran mi error y aprender algo que dejarlo allí en toda su dudosa gloria.
terdon
-2
cmd tty

tty devuelve el nombre del terminal conectado a stdout .

jas
fuente
No estoy seguro de cómo este responde a la pregunta, que es aproximadamente la combinación de comandos; tal vez se expande con un ejemplo de cómo podría lograrlo.
DHAG
Supongo que está diciendo que verifique con ttyel nombre de la terminal y luego use ese archivo como salida, por ejemplo pdftotext file.pdf /dev/pts/2. En ese caso, estoy de acuerdo.
jimmij
Eso se puede abreviar / automatizar a ; que generalmente va a ser equivalente a . Pero este enfoque supone que el objetivo es mostrar la salida de (es decir, en el terminal), y eso no es lo que la pregunta está haciendo (ver los comentarios sobre la respuesta de terdon para obtener alguna aclaración sobre el significado de la pregunta). prog1  input_file $(tty)prog1  input_file /dev/ttyprog1
de Scott