
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 md5sum
s 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 md5sum
salida del programa utiliza dígitos hexadecimales. Entonces usamos la -w32
opción del uniq
comando 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/file
y A/subdir2/otherfile
son 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 cut
o sed
etc. Los dejé en la salida porque son una clave útil para una matriz asociativa (también conocida como 'hash') en awk
o perl
etc 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 cmp
sea una utilidad adecuada y que tanto las carpetas/directorios 1
como los 2
que 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 1
con 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" ;