La pregunta en el aviso de recompensa actual:
El ejemplo general es demasiado complicado. ¿Alguien puede explicar cómo implementar el siguiente ejemplo?diff <(cat "$2" | xz -d) <(cat "$1" | xz -d)
Parece tener una respuesta aquí .
Como se muestra en la respuesta de Gilles , la idea general es enviar la salida de los comandos "productor" a los nuevos archivos 1 del dispositivo en diferentes etapas de una tubería, dejándolos disponibles para los comandos "consumidores", que posiblemente puedan tomar nombres de archivos como argumentos ( asumiendo que su sistema le da acceso a descriptores de archivo como /dev/fd/X
).
La forma más sencilla de lograr lo que está buscando es probablemente:
xz -cd file1.xz | { xz -cd file2.xz | diff /dev/fd/3 -; } 3<&0
(Utilizando file1.xz
en lugar de "$1"
legibilidad y en xz -cd
lugar de cat ... | xz -d
porque un solo comando es suficiente).
La salida del primer comando "productor" xz -cd file1.xz
, se canaliza a un comando compuesto ( {...}
); pero, en lugar de consumirse inmediatamente como la entrada estándar del siguiente comando, se duplica al descriptor de archivo 3
y, por lo tanto, se hace accesible a todo lo que se encuentra dentro del comando compuesto como /dev/fd/3
. La salida del segundo comando "productor" xz -cd file2.xz
, que no consume ni su entrada estándar ni nada del descriptor de archivo 3
, se canaliza al comando "consumidor" diff
, que lee de su entrada estándar y de /dev/fd/3
.
La duplicación de la tubería y del descriptor de archivo se puede agregar para proporcionar archivos de dispositivo para tantos comandos de "productor" como sea necesario, por ejemplo:
xz -cd file1.xz | { xz -cd file2.xz | { diff /dev/fd/3 /dev/fd/4; } 4<&0; } 3<&0
Si bien puede ser irrelevante en el contexto de su pregunta específica, vale la pena señalar que:
cmd1 <(cmd2) <(cmd3)
, cmd2 | { cmd3 | { cmd1 /dev/fd/3 /dev/fd/4; } 4<&0; } 3<&0
y ( cmd2 | ( cmd3 | ( cmd1 /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 )
tienen diferentes efectos potenciales en el entorno de ejecución inicial.
Al contrario de lo que sucede en cmd1 <(cmd2) <(cmd3)
, cmd3
y cmd1
en cmd2 | { cmd3 | { cmd1 /dev/fd/3 /dev/fd/4; } 4<&0; } 3<&0
no podrá leer ninguna entrada del usuario. Eso requerirá más descriptores de archivo. Por ejemplo, para que coincida
diff <(echo foo) <(read var; echo "$var")
necesitarás algo como
{ echo foo | { read var 0<&9; echo "$var" | diff /dev/fd/3 -; } 3<&0; } 9<&0
1 Puede encontrar más información sobre ellos en U&L, por ejemplo, en Understanding / dev y sus subdirecciones y archivos .