Cómo comparar dos archivos de texto en la terminal

¿Necesitas ver las diferencias entre dos revisiones de un archivo de texto? Entonces diff es el comando que necesitas. Este tutorial te muestra cómo usar diff en Linux y macOS, de manera fácil.

Sumergiéndonos en diff

El comando diff compara dos archivos y produce una lista de las diferencias entre los dos. Para ser más exactos, produce una lista de los cambios que deberían realizarse en el primer archivo, para que coincida con el segundo archivo. Si tienes eso en cuenta, te resultará más fácil comprender el resultado diff.

El comando diff fue diseñado para encontrar diferencias entre los archivos de código fuente y para producir una salida que pueda ser leída y ejecutada por otros programas, como el comando patch. En este tutorial, veremos las formas más útiles de usar para los humanos el comando diff.

Vamos a sumergirnos y analizar dos archivos. El orden de los archivos en la línea de comando determina qué archivo diff considera el “primer archivo” y cuál considera que es el “segundo archivo”.

En el ejemplo a continuación, alpha1 es el primer archivo y alpha2 es el segundo archivo. Ambos archivos contienen el alfabeto fonético, pero el segundo archivo, alpha2, se ha modificado aún más para que los dos archivos no sean idénticos.

Podemos comparar los archivos con este comando. Debes escribir diff, un espacio, el nombre del primer archivo, un espacio, el nombre del segundo archivo y luego presiona Enter.

Salida

¿Cómo diseccionamos esa salida? Una vez que sabes qué buscar, no está tan malo. Cada diferencia se enumera a su vez en una sola columna, y cada diferencia está etiquetada. La etiqueta contiene números a cada lado de una letra, como 4c4. El primer número es el número de línea en alpha1, y el segundo número es el número de línea en alpha2. La letra en el medio puede ser:

  • c: La línea en el primer archivo debe cambiarse para que coincida con la línea en el segundo archivo.
  • d: La línea en el primer archivo debe eliminarse para que coincida con el segundo archivo.
  • a: Se debe agregar contenido adicional al primer archivo para que coincida con el segundo archivo.

En nuestro ejemplo 4c4, nos dice que la línea cuatro de alpha1 debe cambiarse para que coincida con la línea cuatro de alpha2. Esta es la primera diferencia entre los dos archivos que se encuentran con diff.

Las líneas que comienzan con < se refieren al primer archivo, en nuestro ejemplo alpha1, y las líneas que comienzan con > se refieren al segundo archivo, alpha2. La línea < Delta nos dice que la palabra Delta es el contenido de la línea cuatro en alpha1. La línea > Dave nos dice que la palabra Dave es el contenido de la línea cuatro en alpha2. Para resumir entonces, necesitamos reemplazar Delta con Dave en la línea cuatro en alpha1, para que esa línea coincida en ambos archivos.

Más ejemplos

El siguiente cambio se indica mediante 12c12. Aplicando la misma lógica, esto nos dice que la línea 12 en alpha1 contiene la palabra Lima, pero la línea 12 de alpha2 contiene la palabra Linux.

El tercer cambio se refiere a una línea que se ha eliminado de alpha2. La etiqueta 21d20 se descifra como “la línea 21 debe eliminarse del primer archivo para que ambos archivos se sincronicen desde la línea 20 en adelante”. La línea < Uniform nos muestra el contenido de la línea que debe eliminarse de alpha1.

La cuarta diferencia está etiquetada como 26a26,28. Este cambio se refiere a tres líneas adicionales que se han agregado a alpha2. Ten en cuenta el 26,28 en la etiqueta. Los números de dos líneas separados por una coma representan un rango de números de línea.

En este ejemplo, el rango es de la línea 26 a la línea 28. La etiqueta se interpreta como “en la línea 26 del primer archivo, debes agregar las líneas 26 a 28 del segundo archivo”. Se nos muestran las tres líneas en alpha2 que necesitan ser agregadas a alpha1. Contienen las palabras Quirk, Strange y Charm.

Revisión rápida

Si todo lo que quieres saber es si dos archivos son iguales, utiliza la opción –s (reportar archivos idénticos).

Puedes usar la opción –q (rápido) para obtener una sentencia igualmente concisa sobre dos archivos diferentes.

Una cosa a tener en cuenta es que, con dos archivos idénticos, la opción –q (rápido) se bloquea por completo y no informa nada en absoluto.

Una vista alternativa

La opción –y (lado a lado) usa un diseño diferente para describir las diferencias de archivo. A menudo es conveniente usar la opción –W (ancho) con la vista de lado a lado, para limitar el número de columnas que se muestran.

Esto evita líneas de ajuste feas que hacen que la salida sea difícil de leer. Aquí le hemos dicho a diff que produzca una pantalla de lado a lado y que limite la salida a 70 columnas.

El primer archivo en la línea de comandos, alpha1, se muestra a la izquierda y la segunda línea en la línea de comando, alpha2, se muestra a la derecha. Se muestran las líneas de cada archivo, una al lado de la otra. Hay caracteres indicadores junto a esas líneas en alpha2 que se han cambiado, eliminado o agregado.

  • El |: Una línea que se ha cambiado en el segundo archivo.
  • <: Una línea que se ha eliminado del segundo archivo.
  • >: Una línea que se ha agregado al segundo archivo que no está en el primer archivo.

Si prefieres un resumen lado a lado más compacto de las diferencias de archivos, debes usar la opción –suppress-common-lines. Esto obliga a diff enumerar solo las líneas modificadas, agregadas o eliminadas.

Añadir un toque de color

Otra utilidad llamada colordiff agrega resaltado de color a la salida diff. Esto hace que sea mucho más fácil ver qué líneas tienen diferencias.

Tienes que utilizar apt-get para instalar este paquete en tu sistema si estás usando Ubuntu u otra distribución basada en Debian. En otras distribuciones de Linux, utiliza la herramienta de administración de paquetes de tu distribución de Linux.

Puedes usar colordiff tal como lo harías con diff.

De hecho, colordiff es un envoltorio para diff y diff hace todo el trabajo detrás de escena. Por eso, todas las opciones de diff funcionarán con colordiff.

Proporcionando algo de contexto

Para encontrar un punto intermedio entre tener todas las líneas en los archivos que se muestran en la pantalla y tener solo las líneas cambiadas en la lista, podemos solicitar a diff un contexto.

Hay dos maneras de hacer esto. Ambas formas logran el mismo propósito, que es mostrar algunas líneas antes y después de cada línea cambiada. Podrás ver lo que sucede en el archivo en el lugar donde se detectó la diferencia.

El primer método usa la opción –c (contexto copiado).

La salida diff tiene un encabezado. El encabezado enumera los dos nombres de archivo y sus tiempos de modificación. Hay asteriscos (*) antes del nombre del primer archivo y guiones (-) antes del nombre del segundo archivo. Se usarán asteriscos y guiones para indicar a qué archivo pertenecen las líneas en la salida.

Una línea de asteriscos con 1,7 en el medio indica que estamos viendo líneas de alpha1. Para ser precisos, estamos viendo las líneas uno a siete. La palabra Delta se marca como modificada. Tiene un signo de exclamación (!) a su lado y es rojo. Hay tres líneas de texto sin cambios que se muestran antes y después de esa línea para que podamos ver el contexto de esa línea en el archivo.

La línea de guiones con 1,7 en el medio nos dice que ahora estamos viendo líneas de alpha2. Nuevamente, estamos viendo las líneas uno a siete, con la palabra Dave en la línea cuatro marcadas como diferente.

Tres líneas de contexto encima y debajo de cada cambio es el valor predeterminado. Puedes especificar cuántas líneas de contexto desea proporcionar diff. Para hacer esto, utiliza la opción –C (contexto copiado) con una “C” mayúscula y proporciona el número de líneas que deseas:

Otra opción

La segunda opción que diff ofrece contexto es la opción –u (contexto unificado).

Como antes, tenemos un encabezado en la salida. Se nombran los dos archivos y se muestran sus tiempos de modificación.

Hay guiones (-) antes del nombre de alpha1 y signos más (+) antes del nombre de alpha2. Esto nos dice que los guiones se usarán para referirse a alpha1 y los signos más se usarán para referirse a alpha2. Dispersos a lo largo de la lista hay líneas que comienzan con signos (@). Estas líneas marcan el inicio de cada diferencia. También nos dicen qué líneas se muestran desde cada archivo.

Se nos muestran las tres líneas antes y después de que la línea marcada sea diferente para que podamos ver el contexto de la línea cambiada.

En la vista unificada, las líneas con la diferencia se muestran una encima de la otra. La línea de alpha1 está precedida por un guión y la línea de alpha2 está precedida por un signo más. Esta pantalla logra en ocho líneas lo que la pantalla de contexto copiado arriba tomó quince para hacer.

Como era de esperar, podemos pedirle a diff que proporcione exactamente la cantidad de líneas de contexto unificado que nos gustaría ver. Para hacer esto, usa la opción -U (contexto unificado) con una “U” mayúscula y proporciona la cantidad de líneas que deseas:

Ignorando el espacio en blanco y entre mayúsculas y minúsculas

Analicemos otros dos archivos, test4 y test5. Estos tienen los seis nombres de superhéroes en ellos.

Los resultados muestran que diff no encuentra nada diferente con las líneas Black Widow, Spider-Man y Thor. Sí marca cambios con las líneas Captain America, Ironman y The Hulk.

Entonces, ¿qué es diferente? Bueno, en test5, Hulk se escribe con una “h” en minúscula, y Captain America tiene un espacio adicional entre “Captain” y “América”. Bien, eso es evidente, pero ¿qué tiene de malo la línea Ironman? No hay diferencias visibles.

Aquí hay una buena regla general. Si no puedes verlo, la respuesta es un espacio en blanco. Es casi seguro que hay un espacio perdido o dos, o un carácter de tabulación, al final de esa línea.

Si no te importan, puedes dar instrucciones a diff para ignorar tipos específicos de diferencia de línea, que incluyen:

  • -i: Ignora las diferencias entre mayúsculas y minúsculas.
  • -Z: Ignora el espacio en blanco final.
  • -b: Ignora los cambios en la cantidad de espacio en blanco.
  • -w: Ignora todos los cambios de espacio en blanco.

Pruebas

Pidamos a diff que compruebe esos dos archivos nuevamente, pero esta vez para ignorar cualquier diferencia entre minúsculas y mayúsculas.

Las líneas con “The Hulk” y “The hulk” ahora se consideran una coincidencia, y no se marcan diferencias para las minúsculas “h”. Pidamos a diff también ignorar los espacios en blanco finales.

Como sospechábamos, el espacio en blanco final debe haber sido la diferencia en la línea Ironman porque diff ya no marca una diferencia para esa línea. Eso deja solo al Captain America. Pidamos a diff ignorar la distinción de mayúsculas e ignorar todos los problemas de espacios en blanco.

Al decirle a diff que ignoremos las diferencias que no nos preocupan, diff nos dice que, para nuestros propósitos, los archivos coinciden.

El comando diff tiene muchas más opciones, pero la mayoría de ellas se relacionan con la producción de salida legible por máquina. Estos se pueden revisar en la página del manual de Linux.

Las opciones que hemos usado en los ejemplos anteriores te permitirán rastrear todas las diferencias entre las versiones de tus archivos de texto, usando la línea de comandos y los globos oculares humanos.