recursivo - diff entre dos archivos linux
Diferencia entre dos directorios en Linux (15)
El complemento DirDiff de vim es otra herramienta muy útil para comparar directorios.
vim -c "DirDiff dir1 dir2"
No solo enumera qué archivos son diferentes entre los directorios, sino que también le permite inspeccionar / modificar con vimdiff los archivos que son diferentes.
Estoy tratando de encontrar los archivos existentes en un directorio pero no en el otro, intenté usar este comando:
diff -q dir1 dir2
El problema con el comando anterior es que encuentra los archivos en dir1
pero no en dir2
, así como los archivos en dir2
pero no en dir1
,
Estoy intentando encontrar los archivos en dir1
pero no solo en dir2
.
Aquí hay una pequeña muestra de cómo se ven mis datos.
dir1 dir2 dir3
1.txt 1.txt 1.txt
2.txt 3.txt 3.txt
5.txt 4.txt 5.txt
6.txt 7.txt 8.txt
Otra pregunta en mi mente es ¿cómo puedo encontrar los archivos en dir1
pero no en dir2
o dir3
en un solo comando?
Esta respuesta optimiza una de las sugerencias de @ Adail-Junior al agregar la opción -D
, que es útil cuando ninguno de los directorios que se comparan son repositorios git:
git diff -D --no-index dir1/ dir2/
Si usa -D
, no verá comparaciones con /dev/null
: text Binary files a/whatever and /dev/null differ
Este es el script de bash para imprimir comandos para sincronizar dos directorios
dir1=/tmp/path_to_dir1
dir2=/tmp/path_to_dir2
diff -rq $dir1 $dir2 | sed -e "s|Only in $dir2/(.*/): /(.*/)|cp -r $dir2/1//2 $dir1/1|" | sed -e "s|Only in $dir1/(.*/): /(.*/)|cp -r $dir1/1//2 $dir2/1|"
Esto debería hacer el trabajo:
diff -rq dir1 dir2
Opciones explicadas (a través de la página man de diff (1)):
-
-r
- Compara recursivamente cualquier subdirectorio encontrado. -
-q
- Salida solo si los archivos difieren.
Esto es un poco tarde pero puede ayudar a alguien. No estoy seguro si diff o rsync escupen solo nombres de archivos en un formato simple como este. Gracias a plhn por dar esa buena solución que amplié a continuación.
Si solo desea los nombres de archivo, así que es fácil copiar los archivos que necesita en un formato limpio, puede usar el comando buscar.
comm -23 <(find dir1 | sed ''s/dir1////''| sort) <(find dir2 | sed ''s/dir2////''| sort) | sed ''s/^///dir1/''
Esto supone que tanto dir1 como dir2 están en la misma carpeta principal. simplemente elimina la carpeta principal para que puedas comparar manzanas con manzanas. El último sed solo vuelve a poner el nombre dir1.
Si solo quieres archivos:
comm -23 <(find dir1 -type f | sed ''s/dir1////''| sort) <(find dir2 -type f | sed ''s/dir2////''| sort) | sed ''s/^///dir1/''
Del mismo modo para los directorios:
comm -23 <(find dir1 -type d | sed ''s/dir1////''| sort) <(find dir2 -type d | sed ''s/dir2////''| sort) | sed ''s/^///dir1/''
GNU grep
puede invertir la búsqueda con la opción -v
. Esto hace que grep
reporte las líneas, que no coinciden. De este modo, puede eliminar los archivos en dir2
de la lista de archivos en dir1
.
grep -v -F -x -f <(find dir2 -type f -printf ''%P/n'') <(find dir1 -type f -printf ''%P/n'')
Las opciones -F -x
dicen a grep
que realice una búsqueda de cadena en toda la línea.
Insatisfecho con todas las respuestas, ya que la mayoría de ellas funcionan muy lentamente y producen resultados innecesariamente largos para directorios grandes, escribí mi propio script de Python para comparar dos carpetas.
A diferencia de muchas otras soluciones, no compara el contenido de los archivos. Tampoco entra dentro de los subdirectorios que faltan en otro directorio. Así que la salida es bastante concisa y el script funciona rápido.
#!/usr/bin/env python3
import os, sys
def compare_dirs(d1: "old directory name", d2: "new directory name"):
def print_local(a, msg):
print(''DIR '' if a[2] else ''FILE'', a[1], msg)
# ensure validity
for d in [d1,d2]:
if not os.path.isdir(d):
raise ValueError("not a directory: " + d)
# get relative path
l1 = [(x,os.path.join(d1,x)) for x in os.listdir(d1)]
l2 = [(x,os.path.join(d2,x)) for x in os.listdir(d2)]
# determine type: directory or file?
l1 = sorted([(x,y,os.path.isdir(y)) for x,y in l1])
l2 = sorted([(x,y,os.path.isdir(y)) for x,y in l2])
i1 = i2 = 0
common_dirs = []
while i1<len(l1) and i2<len(l2):
if l1[i1][0] == l2[i2][0]: # same name
if l1[i1][2] == l2[i2][2]: # same type
if l1[i1][2]: # remember this folder for recursion
common_dirs.append((l1[i1][1], l2[i2][1]))
else:
print_local(l1[i1],''type changed'')
i1 += 1
i2 += 1
elif l1[i1][0]<l2[i2][0]:
print_local(l1[i1],''removed'')
i1 += 1
elif l1[i1][0]>l2[i2][0]:
print_local(l2[i2],''added'')
i2 += 1
while i1<len(l1):
print_local(l1[i1],''removed'')
i1 += 1
while i2<len(l2):
print_local(l2[i2],''added'')
i2 += 1
# compare subfolders recursively
for sd1,sd2 in common_dirs:
compare_dirs(sd1, sd2)
if __name__=="__main__":
compare_dirs(sys.argv[1], sys.argv[2])
Uso de la muestra:
user@laptop:~$ python3 compare_dirs.py dir1/ dir2/
DIR dir1/out/flavor-domino removed
DIR dir2/out/flavor-maxim2 added
DIR dir1/target/vendor/flavor-domino removed
DIR dir2/target/vendor/flavor-maxim2 added
FILE dir1/tmp/.kconfig-flavor_domino removed
FILE dir2/tmp/.kconfig-flavor_maxim2 added
DIR dir2/tools/tools/LiveSuit_For_Linux64 added
O si solo quieres ver los archivos del primer directorio:
user@laptop:~$ python3 compare_dirs.py dir2/ dir1/ | grep dir1
DIR dir1/out/flavor-domino added
DIR dir1/target/vendor/flavor-domino added
FILE dir1/tmp/.kconfig-flavor_domino added
PS Si necesita comparar tamaños de archivos y hashes para posibles cambios, publiqué un script actualizado aquí: https://gist.github.com/amakukha/f489cbde2afd32817f8e866cf4abe779
La respuesta aceptada también mostrará una lista de los archivos que existen en ambos directorios, pero que tienen un contenido diferente. Para listar SOLAMENTE los archivos que existen en dir1 puede usar:
diff -r dir1 dir2 | grep ''Only in'' | grep dir1 | awk ''{print $4}'' > difference1.txt
Explicación:
- diff -r dir1 dir2: compare
- grep ''Only in'': obtiene líneas que contienen ''Only in''
- grep dir1: obtener líneas que contienen dir
Meld ( http://meldmerge.org/ ) hace un gran trabajo al comparar directorios y archivos.
Otro enfoque (quizás más rápido para directorios grandes):
$ find dir1 | sed ''s,^[^/]*/,,'' | sort > dir1.txt && find dir2 | sed ''s,^[^/]*/,,'' | sort > dir2.txt
$ diff dir1.txt dir2.txt
El comando sed
elimina el primer componente del directorio gracias a la publicación de Erik )
Una buena manera de hacer esta comparación es usar find
con md5sum
, y luego un diff
.
Ejemplo:
Utilice find
para enumerar todos los archivos en el directorio, luego calcule el hash md5 para cada archivo y canalícelo a un archivo:
find /dir1/ -type f -exec md5sum {} /; > dir1.txt
Realice el mismo procedimiento en el otro directorio:
find /dir2/ -type f -exec md5sum {} /; > dir2.txt
Luego compara el resultado dos archivos con "diff":
diff dir1.txt dir2.txt
Esta estrategia es muy útil cuando los dos directorios que se comparan no están en la misma máquina y debe asegurarse de que los archivos sean iguales en ambos directorios.
Otra buena manera de hacer el trabajo es usando git.
git diff --no-index dir1/ dir2/
¡Atentamente!
Una forma simplificada de comparar 2 directorios usando el comando DIFF
diff filename.1 filename.2> filename.dat >> Entrar
abrir filename.dat una vez finalizada la ejecución
y verá: Solo en nombre_archivo.1: nombre_archivo.2 Solo en: nombre_directorio: nombre_de_archivo1 Solo en: nombre_directorio: nombre_de_archivo2
kdiff3 tiene una interfaz agradable para archivos y directorios.
Compruebe la URL: http://kdiff3.sourceforge.net
Funciona bajo Windows y Linux.
comm -23 <(ls dir1 |sort) <(ls dir2|sort)
Este comando le dará archivos que están en dir1 y no en dir2.
Acerca del signo <( )
, puede buscarlo en Google como ''sustitución de proceso''.
diff -r dir1 dir2 | grep dir1 | awk ''{print $4}'' > difference1.txt
Explicación:
diff -r dir1 dir2
muestra qué archivos están solo en dir1 y aquellos solo en dir2 y también los cambios de los archivos presentes en ambos directorios, si los hay.diff -r dir1 dir2 | grep dir1
diff -r dir1 dir2 | grep dir1
muestra qué archivos están solo en dir1awk
para imprimir solo nombre de archivo.