En la primera parte de esta serie de tutoriales del comando diff, discutimos los conceptos básicos del comando, incluido cómo funciona y cómo se puede comprender la salida que produce. Si bien definitivamente hay un poco de curva de aprendizaje involucrada con esta utilidad de línea de comandos, vale la pena aprender, especialmente si su trabajo diario implica realizar tareas relacionadas con archivos en máquinas Linux solo con CLI.
Suponiendo que ya conoce el uso básico del comando diff, en este tutorial analizaremos las diversas opciones de línea de comandos que ofrece la herramienta, a través de algunos ejemplos fáciles de entender.
Pero antes de continuar, tenga en cuenta que todos los ejemplos de este tutorial se probaron en Ubuntu 14.04 con Bash versión 4.3.11(1) y diff versión 3.3.
Opciones de comando Diff
1. Informar cuando los archivos son idénticos
De forma predeterminada, cuando el comando diff detecta que los archivos que se comparan son idénticos, no produce ningún resultado.
$ diff file1 file2
$
Pero, existe una opción de línea de comando (-s) con la que puede forzar el comando para informar esto en la salida:
$ diff -s file1 file2
Files file1 and file2 are identical
2. Contexto copiado y contexto unificado
Estos son básicamente dos formatos diferentes en los que el comando diff puede producir su salida. El contexto copiado se habilita con la opción de línea de comando -c, mientras que el contexto unificado se habilita con -u. El siguiente es un ejemplo de lo anterior:
$ diff -c file1 file2
*** file1 2016-12-29 09:36:47.175597647 +0530
--- file2 2016-12-29 09:19:55.799558326 +0530
***************
*** 1,3 ****
Hi
! Helllo
Bye
--- 1,3 ----
Hi
! Hello
Bye
Por lo tanto, en el formato de salida de contexto Copiado, las líneas diferentes se indican con un signo de exclamación (!).
Y aquí está el ejemplo del formato de contexto unificado:
$ diff -u file1 file2
--- file1 2016-12-29 09:36:47.175597647 +0530
+++ file2 2016-12-29 09:19:55.799558326 +0530
@@ -1,3 +1,3 @@
Hi
-Helllo
+Hello
Bye
En este formato de salida, +
y -
los símbolos antes de las líneas indican versiones de la línea diferente: '-' cuando la línea en el archivo1
falta en el archivo 2
, '+' cuando la línea en el archivo 2
se agregó al archivo 1.
3. Salida de un script 'ed'
El comando diff también es capaz de producir comandos que el editor 'ed' puede usar para convertir el archivo original (archivo1 en nuestros ejemplos aquí) en el nuevo archivo (archivo2). Así es como se hace esto:
Supongamos que file1 y file2 contienen el siguiente cambio:
$ diff file1 file2
2c2
< Helllo
---
> Hello
Ahora, use la opción de línea de comando -e para producir la salida que el editor 'ed' entiende, y redirija esa salida a un archivo:
diff -e file1 file2 > out
Esto es lo que fuera contiene en este caso:
2c
Hello
.
Lo que necesita a continuación es agregar el comando 'w' al final de out archivo.
2c
Hello
.
w
Ahora, ejecuta el siguiente comando:
ed - file1 < out
Y verá que el archivo 1 y el archivo 2 ahora son idénticos.
$ diff file1 file2
$
Para obtener más información sobre esta funcionalidad, diríjase aquí.
4. Producir resultados en dos columnas
Normalmente, el comando diff produce una salida de la siguiente manera:
$ diff file1 file2
2c2
< Helllo
---
> Hello
Pero existe una opción de línea de comando (-y) que dirige diff para producir resultados en dos columnas separadas. He aquí un ejemplo:
$ diff -y file1 file2
Hi Hi
Helllo | Hello
Bye Bye
Como puede ver, este formato de salida usa un '|' para indicar líneas que las diferencian.
5. Ocultar líneas comunes
Si observa el resultado que se muestra en la sección anterior (punto 4 anterior), notará que con -y opción de línea de comando, diff - en la salida - también produce líneas comunes. En caso de que necesite suprimir estas líneas idénticas, puede utilizar --suppress-common-lines opción.
[email protected]:~$ diff -y --suppress-common-lines file1 file2
Helllo | Hello
6. Mostrar la función C en la que se encuentra cada cambio
Para los casos en los que usa diff para comparar dos archivos de lenguaje C, hay una opción de línea de comando (-p) que indica a la utilidad que muestre con precisión en qué función C se encuentra cada cambio. Por ejemplo, suponga que estos son los dos archivos C:
archivo1.c:
#include<stdio.h>
void compare(float x, float y)
{
if(x == y) // incorrect way
{
printf("\n EQUAL \n");
}
}
int main(void)
{
compare(1.234, 1.56789);
return 0;
}
archivo2.c:
#include<stdio.h>
void compare(float x, float y)
{
if(x == y)
{
printf("\n EQUAL \n");
}
}
int main(void)
{
compare(1.234, 1.56789);
return 0;
}
Aquí está el resultado cuando ambos archivos se comparan normalmente:
$ diff file1.c file2.c
5c5
< if(x == y) // incorrect way
---
> if(x == y)
Y aquí está el resultado, cuando los archivos se comparan usando -p opción:
$ diff -p file1.c file2.c
*** file1.c 2016-12-29 11:45:36.587010816 +0530
--- file2.c 2016-12-29 11:46:39.823013274 +0530
***************
*** 2,8 ****
void compare(float x, float y)
{
! if(x == y) // incorrect way
{
printf("\n EQUAL \n");
}
--- 2,8 ----
void compare(float x, float y)
{
! if(x == y)
{
printf("\n EQUAL \n");
}
Como puede ver, con -p , diff le brinda una vista más detallada de dónde está el cambio, indicando las líneas diferentes con un signo de exclamación (!).
7. Compara recursivamente subdirectorios
El comando diff también le permite comparar subdirectorios de forma recursiva, pero ese no es su comportamiento predeterminado. Lo que quiero decir es, si tomas el siguiente caso:
$ diff diff-files/ second-diff-files/
diff diff-files/file1 second-diff-files/file1
1c1
< Hi
---
> i
diff diff-files/file2 second-diff-files/file2
2c2
< Hello
---
> ello
El comando diff solo comparó archivos en los directorios de nivel superior, pero si usa la opción de línea de comando -r (que es para diff recursivo), verá que se comparan incluso los archivos presentes en los subdirectorios:
$ diff -r diff-files/ second-diff-files/
diff -r diff-files/file1 second-diff-files/file1
1c1
< Hi
---
> i
diff -r diff-files/file2 second-diff-files/file2
2c2
< Hello
---
> ello
diff -r diff-files/more-diff-files/file1 second-diff-files/more-diff-files/file1
1c1
< Hi
---
> i
diff -r diff-files/more-diff-files/file2 second-diff-files/more-diff-files/file2
2c2
< Hello
---
> ello
8. Tratar los archivos ausentes como vacíos
El comando diff también proporciona una opción mediante la cual puede dirigir la herramienta para que trate los archivos ausentes como vacíos. Por ejemplo, si compara el archivo 1 con el archivo 3 (que no existe), el comportamiento predeterminado de diff es generar un error:
$ diff file1 file3
diff: file3: No such file or directory
Esto no está mal per se; de hecho, esto tiene mucho sentido. Pero puede haber casos en los que no desee que el comando diff arroje un error para tales situaciones (¿mientras es parte de un script bash, puede ser?), entonces para esos escenarios, puede usar la opción de línea de comando -N que obliga al comando a tratar los archivos ausentes como vacíos y continuar con la comparación.
$ diff -N file1 file3
1,5d0
< Hi
<
< Helllo
<
< Bye
Conclusión
Si revisa ambas partes de esta serie de tutoriales correctamente y practica todos los ejemplos que contienen los artículos, entonces no será exagerado decir que terminará teniendo un buen dominio de la herramienta. Por supuesto, no pudimos discutir todo lo relacionado con diff en esta serie, pero puede estar seguro de que muchas de las características/funcionalidades importantes se han cubierto.
Para aquellos que deseen saber más sobre la utilidad, la página del manual siempre está ahí para ustedes. Y sin mencionar que debe seguir usando la herramienta con frecuencia con diferentes conjuntos de archivos para simular diferentes casos de uso.