Extraiga archivos idénticos de dos directorios

Extraiga archivos idénticos de dos directorios

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 de los dos directorios es idéntico.

Quiero copiar todos los archivos que se encuentran en ambos directorios a un tercer directorio. ("Ocurrir en ambos" significa tener el mismo contenido, no el mismo nombre).

Respuesta1

Suponiendo que sus nombres de archivos no tengan espacios en blanco y que no haya subdirectorios en ninguno de los directorios, lo siguiente imprimirá pares de nombres de archivos 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 archivos (o rutas) pueden incluir espacios en blanco, necesitarás ser más inteligente.

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

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

NO UTILICEsum

sumgenera una suma de comprobació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 sumas de comprobación de 16 bits. md5sumTampoco es absolutamente seguro, pero las probabilidades de una colisión con sumas de comprobación de 128 bits son mínimas. 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).

Respuesta2

Usando tu 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 de awk para revisarla antes de emitir las copias, si lo desea

Respuesta3

esto podría funcionar, como ocurre con mpez0 y para copiar los dups.

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

información relacionada