¿Cómo puedo comparar diferentes archivos sin abrirlos?

¿Cómo puedo comparar diferentes archivos sin abrirlos?

Tengo dos directorios A y B; cada uno contiene muchos subdirectorios

geom001, geom002 ....etc

cada subdirectorio contiene un archivo llamado resultados. Quiero comparar, sin abrir ninguno de ellos, cada archivo en A con cada archivo en B y encontrar si hay un archivo o más en A similar a uno o más archivos en B. ¿Cómo puedo usar un comando como el siguiente en un ¿Bucle para buscar en todos los archivos?

cmp --silent  file1 file2  || echo "file1 and file2 are different"

Respuesta1

Si los archivos son exactamente iguales, entonces sus md5sums serán exactamente iguales, por lo que puedes usar:

find A/ B/ -type f -exec md5sum {} + | sort | uniq -w32 -D

Una suma md5 siempre tiene exactamente 128 bits (o 16 bytes o 32 dígitos hexadecimales) de largo, y la md5sumsalida del programa utiliza dígitos hexadecimales. Entonces usamos la -w32opción del uniqcomando para comparar solo los primeros 32 caracteres de cada línea.

Esto se imprimirátodoarchivos con un md5sum no único. es decir, duplicados.

NOTA: esto detectará archivos duplicados sin importar dónde estén en A/ o B/; por lo tanto, si /A/subdir1/filey A/subdir2/otherfileson iguales, se imprimirán igualmente. Si hay varios duplicados, se imprimirán todos.

Puede eliminar los md5sums de la salida mediante canalización, por ejemplo, awk '{print $2}'o con cuto sedetc. Los dejé en la salida porque son una clave útil para una matriz asociativa (también conocida como 'hash') en awko perletc para más Procesando.

Respuesta2

Creo que esto te acercará. Enumerará la salida cmp para todos los archivos denominados resultados en A en comparación con todos los archivos denominados resultados en B.

find ./A -name results | xargs -I REPLACESTR find ./B -name results -exec cmp REPLACESTR {} \;

Respuesta3

Los aparentes desafíos de la pregunta/solicitud son quizás el aspecto de la recursividad.

Suponiendo que cmpsea una utilidad adecuada y que tanto las carpetas/directorios 1como los 2que se van a comparar tengan la misma estructura (es decir, los mismos archivos y carpetas) y residan en la misma ruta raíz, puede intentar algo similar a:

#!/bin/bash
ROOT=$PWD ; # #// change to absolute path eg: /home/aphorise/my_files
PWD1="1/*" ;
PWD2="2/*" ;

# #// Get lengths of seperators
IFS=/ read -a DP <<< ${ROOT} ;
PLEN1=${#DP[*]} ;
IFS=/ read -a DP <<< ${PWD1} ;
PLEN1=$(echo "${#DP[*]}" + $PLEN1 - 1 | bc) ;
IFS=/ read -a DP <<< ${PWD2} ;
PLEN2=${#DP[*]} ;

# #// Set absolute paths:
PWD1="${ROOT}/${PWD1}" ;
PWD2="${ROOT}/${PWD2}" ;
DIFFS=0 ;

function RECURSE()
{
    for A_FILE in $1 ; do
        if [ -d $A_FILE ] ; then
            RECURSE "$A_FILE/*" ;
        else
            IFS=/ read -a FP <<< ${A_FILE} ;
            B_FILE="${PWD2:0:${#PWD2}-${#PLEN2}}$( IFS=/ ; printf "%s" "${FP[*]:$PLEN1:512}"; )" ;
            if ! cmp ${A_FILE} ${B_FILE} 1>/dev/null ; then printf "$A_FILE --> $B_FILE <-- DIFFER.\n" ; ((++DIFFS)) ; fi ;
        fi ;
    done ;
}

printf "Starting comparison on $PWD1 @ $(date)\n\n" ;
RECURSE "${PWD1[*]}" ;
if ((DIFFS != 0)) ; then printf "\n= $DIFFS <= differences detected.\n" ; fi ;
printf "\nCompleted comparison @ $(date)\n" ;

ACTUALIZAR:

Siguiendo con otra secuencia de comandos, después de recibir comentarios adicionales, para comparar incondicionalmente todos los archivos en el directorio 1con 2:

#!/bin/bash
PWD1="$PWD/1/*" ;
PWD2="$PWD/2/*" ;
DIFFS=0 ;
NODIFFS=0 ;

printf "Starting comparison on $PWD1 @ $(date)\n\n" ;

FILES_A=$(find ${PWD1} -type f) ;
FILES_B=$(find ${PWD2} -type f) ;

for A_FILE in ${FILES_A[*]} ; do
        for B_FILE in ${FILES_B[*]} ; do
                if ! cmp ${A_FILE} ${B_FILE} 1>/dev/null ; then
                        printf "$A_FILE & $B_FILE <- DIFFER.\n" ;
                        ((++DIFFS)) ;
                else
                        printf "\n-> SAME: $A_FILE & $B_FILE\n" ;
                        ((++NODIFFS)) ;
                fi ;
        done ;
done ;

printf "\n= $DIFFS <= differences detected - & - $NODIFFS <= exact matches.\n" ;
printf "\nCompleted comparison @ $(date)\n" ;

información relacionada