¿Cómo diferenciar múltiples archivos en directorios?

19

Estoy tratando de encontrar diffcorreos electrónicos entre todos los archivos con los mismos nombres en dos copias de un directorio (por ejemplo, un trabajo y una copia de seguridad). Por ejemplo, puedo diffdos archivos del mismo nombre en ambos:

> diff d1/f.cpp d2/f.cpp

o puedo encontrar diferencias entre los directorios:

> diff d1 d2

pero, ¿cómo puedo encontrar diferencias solo entre los *.cpparchivos?

> diff d1/*.cpp d2/*.cpp

no parece funcionar (por razones obvias).

[Probablemente sea fácil de resolver con bucles, pero estoy tratando de encontrar una forma más elegante]

ysap
fuente

Respuestas:

13

Puede usar un bucle de shell que ejecuta diff para cada archivo, aunque esto no detectará los casos en que d2 contiene un archivo, pero d1 no. Sin embargo, podría ser suficiente.

for file in d1/*.cpp; do
    diff "$file" "d2/${file##*/}"
done

O todo en una línea:

for file in d1/*.cpp; do diff "$file" "d2/${file##*/}"; done

La ${file##*/}parte es una expansión de parámetros especiales.

Si la variable de fichero contiene d1/hello.cpp, a continuación, "${file##*/}"se expandirá a hello.cpp(el valor de archivo, pero con todo lo que hasta, e incluyendo, la última / retirado).

Así "d2/${file##*/}"resultará d2/hello.cppy el comando diff resultante es asídiff d1/hello.cpp d2/hello.cpp

Consulte http://mywiki.wooledge.org/BashFAQ/100 para obtener más información sobre las manipulaciones de cadenas en bash.

En una nota al margen, un sistema de control de versiones (como subversión, git, mercurial, etc.) haría que este tipo de diferencia sea mucho más fácil.

geirha
fuente
Creo que de las dos excelentes respuestas, esto es más sencillo cuando hay varios tipos de archivos (aunque mencioné en la pregunta que estoy buscando una solución sin bucles), así que lo acepté. La única adición agregada es echo "${file##*/}";antes del diffcomando, por lo que uno sabe qué archivos se están comparando realmente. Además, como se menciona en la respuesta de @ Rinzwind, este método no cubre el caso donde la lista de archivos no es exactamente la misma en ambos directorios.
ysap
52

diff -qr {DIR1} {DIR2} hace todos los archivos en ambos directorios.

  • q muestra solo diferencias
  • rHace recursivo. Déjalo afuera si no necesitas eso

No puede indicarle diffdirectamente que use comodines, pero puede agregar:

-x PAT  --exclude=PAT
    Exclude files that match PAT.

-X FILE    --exclude-from=FILE
   Exclude files that match any pattern in FILE.

para excluir archivos. Entonces, si solo desea que *.cppel método más fácil sea crear un archivo de texto que enumere todos los archivos que no lo son *.cpp. Puede hacer esto con el siguiente comando: ls -I "*.cpp" > excluded_filesdonde el -I "*.cpp"argumento ignora todos los archivos .cpp. Tenga en cuenta que las comillas son necesarias.

Rinzwind
fuente
Simple, y funciona a la perfección.
Jose Gómez
4

Algún tiempo después de hacer la pregunta, descubrí la meldutilidad diff, y la estoy usando desde entonces. Este es un gran programa basado en GUI que hace que la comparación y fusión entre archivos y directorios sea una tarea muy fácil. Hace comparaciones de dos o tres vías.

Específicamente, responde a mi pregunta original porque muestra una comparación codificada por colores de los contenidos del directorio y le permite comparar archivos específicos haciendo doble clic en el nombre del archivo.

Si uno necesita más que una comparación de tres vías, entonces gvimdiff(según el vimeditor) también es una excelente opción que proporciona esta funcionalidad.

ysap
fuente