Digamos que también tengo programas a
y b
que puedo ejecutar con ./a
y ./b
.
¿Es posible diferenciar sus resultados sin primero escribir en archivos temporales?
Digamos que también tengo programas a
y b
que puedo ejecutar con ./a
y ./b
.
¿Es posible diferenciar sus resultados sin primero escribir en archivos temporales?
Respuestas:
Use <(command)
para pasar la salida de un comando a otro programa como si fuera un nombre de archivo. Bash canaliza la salida del programa a una canalización y pasa un nombre de archivo como /dev/fd/63
al comando externo.
diff <(./a) <(./b)
Del mismo modo, puede usar >(command)
si desea canalizar algo en un comando.
Esto se llama "Sustitución de proceso" en la página de manual de Bash.
-bash: syntax error near unexpected token ('
. Lo intenté de nuevo sin paréntesis y lo conseguí -bash: java: No such file or directory
. ¿No funciona si el comando tiene parámetros?
alias diffcmd bash -c \'diff \<\(sh -c \!:1\) \<\( sh -c \!:2 \)\'
. (Entonces, por ejemplo: diffcmd "ls" "ls -a").
fseek
, ofertas zsh =(./a)
que se pueden utilizar de forma idéntica a <(./a)
, pero utiliza un archivo temporal bajo el capó, que zsh eliminará para usted.)
Agregando a ambas respuestas, si desea ver una comparación lado a lado, use vimdiff
:
vimdiff <(./a) <(./b)
Algo como esto:
vimdiff
crea vistas de comparación de diferencias hermosas, inteligentes e interactivas. Parece venir con el vim
paquete en la mayoría de los sistemas.
vimdiff
también muestra no solo la línea que difiere sino también el fragmento de texto específico que difiere.
Una opción sería utilizar tuberías con nombre (FIFO) :
mkfifo a_fifo b_fifo
./a > a_fifo &
./b > b_fifo &
diff a_fifo b_fifo
... pero la solución de John Kugelman es mucho más limpia.
rm a_fifo b_fifo
.
Para cualquier persona curiosa, así es como se realiza la sustitución del proceso al usar el shell Fish :
Intento:
diff <(./a) <(./b)
Pez:
diff (./a | psub) (./b | psub)
Desafortunadamente, la implementación en peces es actualmente deficiente ; fish se colgará o usará un archivo temporal en el disco. Tampoco puede usar psub para la salida de su comando.
Agregar un poco más a las respuestas ya buenas (¡me ayudó!):
El comando docker
envía su ayuda a STD_ERR
(es decir, descriptor de archivo 2)
Quería ver si docker attach
y docker attach --help
daba el mismo resultado
$ docker attach
$ docker attach --help
Después de escribir esos dos comandos, hice lo siguiente:
$ diff <(!-2 2>&1) <(!! 2>&1)
!! es lo mismo que! -1, lo que significa ejecutar el comando 1 antes de este: el último comando
! -2 significa ejecutar el comando dos antes de este
2> & 1 significa enviar la salida file_descriptor 2 (STD_ERR) al mismo lugar que la salida file_descriptor 1 (STD_OUT)
Espero que esto haya sido de alguna utilidad.
Para zsh, el uso =(command)
crea automáticamente un archivo temporal y lo reemplaza =(command)
con la ruta del archivo en sí. Con la sustitución de proceso normal, $(command)
se reemplaza con la salida del comando.
Esta función zsh es muy útil y se puede usar para comparar la salida de dos comandos con una herramienta diff, por ejemplo, Beyond Compare:
bcomp =(ulimit -Sa | sort) =(ulimit -Ha | sort)
Para Beyond Compare, tenga en cuenta que debe usar bcomp
lo anterior (en lugar de bcompare
) desde que bcomp
inicia la comparación y espera a que se complete. Si lo usa bcompare
, inicia la comparación e inmediatamente se cierra debido a que los archivos temporales creados para almacenar la salida de los comandos desaparecen.
Lea más aquí: http://zsh.sourceforge.net/Intro/intro_7.html
También tenga en cuenta esto:
Tenga en cuenta que el shell crea un archivo temporal y lo elimina cuando finaliza el comando.
y el siguiente, que es la diferencia entre $(...)
y =(...)
:
Si lee la página de manual de zsh, puede notar que <(...) es otra forma de sustitución de proceso que es similar a = (...). Hay una diferencia importante entre los dos. En el caso <(...), el shell crea una tubería con nombre (FIFO) en lugar de un archivo. Esto es mejor, ya que no llena el sistema de archivos; pero no funciona en todos los casos. De hecho, si hubiéramos reemplazado = (...) con <(...) en los ejemplos anteriores, todos habrían dejado de funcionar, excepto fgrep -f <(...). No puede editar una tubería o abrirla como una carpeta de correo; fgrep, sin embargo, no tiene problemas para leer una lista de palabras de una tubería. Quizás se pregunte por qué la barra diff <(foo) no funciona, ya que foo | trabajos de barra diferencial; esto se debe a que diff crea un archivo temporal si nota que uno de sus argumentos es -, y luego copia su entrada estándar al archivo temporal.