Extraer archivos idénticos de dos directorios.

0

Estoy buscando una solución de Linux para el siguiente problema:

Dados dos directorios con una gran cantidad de archivos. Todos los nombres de archivos son aleatorios y diferentes en ambos directorios. Sin embargo, el contenido de algunos de los archivos en los dos directorios es idéntico.

Quiero copiar todos los archivos que ocurren en ambos directorios a un tercer directorio. ("Ocurre en ambos" significa que tiene el mismo contenido, no el mismo nombre).

Mel
fuente

Respuestas:

1

Asumiendo que sus nombres de archivo no tienen ningún espacio en blanco y no hay subdirectorios en ninguno de los directorios, lo siguiente imprimirá pares de nombres de archivo con sumas MD5 coincidentes:

join -o 1.2,2.2 <(md5sum $D1/* | sort) <(md5sum $D2/* | sort)

Para obtener solo uno de los nombres de archivo, use -o 1.2o -o 2.2.

Si los nombres de archivo (o rutas) pueden incluir espacios en blanco, deberá ser más inteligente.

Si un solo directorio puede tener el mismo archivo con más de un nombre, también deberá ser más inteligente, y deberá decidir exactamente qué hacer. Una posibilidad sería filtrar los duplicados antes de hacer la unión:

join -o 1.2,2.2 <(md5sum $D1/* | sort | uniq -w16) \
                <(md5sum $D2/* | sort | uniq -w16)

NO UTILICE sum

sumgenera una suma de verificación de 16 bits; Si tiene incluso un par de cientos de archivos en cada directorio, es probable que obtenga un falso positivo si compara las sumas de verificación de 16 bits. md5sumtampoco es absolutamente seguro, pero las posibilidades de una colisión con sumas de comprobación de 128 bits son muy pequeñas. En caso de duda, y si es realmente importante, cmplos archivos también:

join -o 1.2,2.2 <(md5sum $D1/* | sort) <(md5sum $D2/* | sort) |
while read F1 F2; do
  if cmp -s $F1 $F2; then
    cp F1 $D3
  fi
done

(Nuevamente, eso no funcionará si los archivos pueden tener espacios en blanco en sus nombres).

rici
fuente
0

Usando su shell favorito para este pseudocódigo:

cd D1; sum * | while read l; do echo "D1 $l"; done >/tmp/foo
cd D2; sum * | while read l; do echo "D2 $1"; done >>/tmp/foo

sort -n /tmp/foo | awk '
$1 == prev_cs { echo "cp $3 dest"}
     /prev_cs = $1/
' | shell

Puede guardar la salida awk para su revisión antes de emitir las copias, si lo desea

mpez0
fuente
sumes realmente una mala idea, ver en.wikipedia.org/wiki/Birthday_problem . Si tiene 300 archivos aleatorios diferentes, las probabilidades son más o menos iguales de que dos de ellos tengan lo mismo sum.
rici
Luego elija un algoritmo de suma de comprobación diferente, como openssl dgst -md5. Mismo código
mpez0
0

esto podría hacer el trabajo, como con mpez0's ans para copiar los dups.

find {tst1,tst2} -exec sum {} {} \; 2> /dev/null | sort | uniq

Amos Folarin
fuente