Una línea con 2 archivos tmp (no lo que quieres) sería:
foo | bar > file1.txt && baz | quux > file2.txt && diff file1.txt file2.txt
Con bash , puedes intentarlo:
diff <(foo | bar) <(baz | quux)
foo | bar | diff - <(baz | quux) # or only use process substitution once
La segunda versión le recordará más claramente qué entrada fue cuál, mostrando
-- /dev/stdin
vs. ++ /dev/fd/63
o algo, en lugar de dos fds numerados.
Ni siquiera aparecerá una canalización con nombre en el sistema de archivos, al menos en los sistemas operativos donde bash puede implementar la sustitución de procesos mediante el uso de nombres de archivo como /dev/fd/63
para obtener un nombre de archivo que el comando puede abrir y leer para leer realmente desde un descriptor de archivo ya abierto que bash establece antes de ejecutar el comando. (es decir, bash usa pipe(2)
antes de fork, y luego dup2
para redirigir desde la salida quux
a un descriptor de archivo de entrada para diff
, en fd 63.)
En un sistema sin "mágico" /dev/fd
o /proc/self/fd
, bash podría usar canalizaciones con nombre para implementar la sustitución del proceso, pero al menos las administraría por sí mismo, a diferencia de los archivos temporales, y sus datos no se escribirían en el sistema de archivos.
Puede verificar cómo bash implementa la sustitución de procesos echo <(true)
para imprimir el nombre del archivo en lugar de leerlo. Se imprime /dev/fd/63
en un sistema Linux típico. O para obtener más detalles sobre exactamente qué llamadas al sistema usa bash, este comando en un sistema Linux rastreará las llamadas al sistema de archivos y descriptores de archivos
strace -f -efile,desc,clone,execve bash -c '/bin/true | diff -u - <(/bin/true)'
Sin bash, podrías hacer una pipa con nombre . Use -
para indicar diff
que lea una entrada de STDIN y use la tubería nombrada como la otra:
mkfifo file1_pipe.txt
foo|bar > file1_pipe.txt && baz | quux | diff file1_pipe.txt - && rm file1_pipe.txt
Tenga en cuenta que solo puede canalizar una salida a múltiples entradas con el comando tee:
ls *.txt | tee /dev/tty txtlist.txt
El comando anterior muestra la salida de ls * .txt al terminal y la envía al archivo de texto txtlist.txt.
Pero con la sustitución de procesos, puede usar tee
para alimentar los mismos datos en múltiples canales:
cat *.txt | tee >(foo | bar > result1.txt) >(baz | quux > result2.txt) | foobar
mkfifo a; cmd >a& cmd2|diff a -; rm a
pipeline1 | diff -u - <(pipeline2)
. Luego, la salida le recordará más claramente qué entrada fue cuál, mostrando-- /dev/stdin
vs.++ /dev/fd/67
o algo, en lugar de dos fds numerados.foo <( pipe )
) no modifica el sistema de archivos. La pipa es anónima ; no tiene nombre en el sistema de archivos . El shell utiliza lapipe
llamada del sistema para crearlo, nomkfifo
. Utilícelostrace -f -efile,desc,clone,execve bash -c '/bin/true | diff -u - <(/bin/true)'
para rastrear llamadas de sistema de archivo y descriptor de archivo si desea verlo usted mismo. En Linux,/dev/fd/63
es parte del/proc
sistema de archivos virtual; automáticamente tiene entradas para cada descriptor de archivo, y no es una copia de los contenidos. Así que no puede llamar a eso un "archivo temporal" a menos quefoo 3<bar.txt
cuenteEn bash puede usar subshells, para ejecutar las tuberías de comando individualmente, encerrando la tubería entre paréntesis. A continuación, puede prefijarlos con <para crear canalizaciones con nombre anónimo que luego puede pasar a diff.
Por ejemplo:
Las canalizaciones con nombre anónimo son administradas por bash, por lo que se crean y destruyen automáticamente (a diferencia de los archivos temporales).
fuente
Algunas personas que llegan a esta página podrían estar buscando una diferencia línea por línea, para lo cual
comm
ogrep -f
deberían usarse en su lugar.Una cosa a destacar es que, en todos los ejemplos de respuestas, las diferencias no comenzarán realmente hasta que ambas transmisiones hayan terminado. Pruebe esto con, por ejemplo:
Si esto es un problema, puede probar sd (stream diff), que no requiere la clasificación (como lo
comm
hace) ni la sustitución del proceso como en los ejemplos anteriores, es órdenes o magnitud más rápido quegrep -f
y admite flujos infinitos.El ejemplo de prueba que propongo se escribiría así en
sd
:Pero la diferencia es que
seq 100
se diferenciaría deseq 10
inmediato. Tenga en cuenta que, si una de las transmisiones es untail -f
, la diferencia no se puede hacer con la sustitución del proceso.Aquí hay una entrada de blog que escribí sobre diffing corrientes en el terminal, que introduce
sd
.fuente