
Necesito encontrar todos los archivos que existen en cualquier lugar de dir1
, pero que no existen en ningún lugar de dir2
. dir1
y dir2
puede tener una estructura diferente, por lo que diff -r
no funciona bien.
Respuesta1
Intente hacer una lista de archivos sin ruta. De esa manera, puede comparar dos directorios. Sin embargo, todos los nombres de archivos deberían ser diferentes. Si tiene el mismo nombre de archivo repetido en dir1 en diferentes subdirectorios, eliminar la ruta eliminará la unicidad del nombre de archivo. Puede obtener una lista de cada directorio sin nombres de ruta como este:
find dir1/ -exec basename {} \; | sort
find dir2/ -exec basename {} \; | sort
Todos juntos se verían así
diff <(find dir1/ -exec basename {} \; | sort) <(find dir2/ -exec basename {} \; | sort)
Veo que hay un comentario que sugiere el uso de fdupes. fdupes
Si definitivamente es una mejor solución.
Respuesta2
Un método burdo podría ser el uso de md5sum
. Solo tenga en cuenta que los archivos con longitud cero siempre se verán como duplicados, por lo que es posible que desee almacenar find
solo archivos con un tamaño de al menos un byte.
find /first/path -type f -exec md5sum -b \{\} \; > /tmp/md5-path1.txt
cut -b1-32 < /tmp/md5-path1-short.txt
find /second/path -type f -exec md5sum -b \{\} \; > /tmp/md5-path2.txt
cut -b1-32 < /tmp/md5-path2-short.txt
Archivos en la ruta1 que no están en la ruta2 (elimine la opción '-v'
grep /tmp/md5-path1.txt -v -F -f /tmp/md5/path2-short.txt
Nivel CYA: profesional
El 32 anterior se debe a que los hashes MD5 tienen 32 bytes de longitud. Si usara, digamos, sha1sum
, que tiene una probabilidad aún menor de colisiones, entonces usaría una longitud de 40; sha224sum
requiere 56, sha256sum
requiere 64 y sha512sum
128.
Nivel CYA: paranoico
Es posible que esto no funcione en algunos esquemas de almacenamiento en caché en los que los metadatos se guardan en archivos.cuyo nombre contiene el hash del archivo original.
(Esto realmente me pasó con una instalación de Wordpress + Magento hace años, donde queríamos migrar un caché de artículos enorme y eliminar las entradas obsoletas).
En este caso, tendría que usar un esquema de hash diferente (solución rápida) para evitar grep
devolver falsos positivos, confundiendo la entrada de metadatos con el archivo original (por lo tanto, use SHA1 si el caché usa MD5 o viceversa); o usar sed
para reescribir todas las líneas en los archivos "cortos" para agregar un "^" al principio, convirtiéndolo así en una expresión regular anclada y eliminando la -F
bandera grep
para procesar el archivo como expresiones regulares en lugar de cadenas simples.
Respuesta3
Entonces, la solución parcial que encontré es:
find dir1 -type f | grep -vxFf <(fdupes -r dir1 dir2)
pero digo "parcial", porque si hay duplicados en dir1
, no se mostrarán, por lo que debes ejecutarlo fdupes -r dir1
primero.