¿La forma más rápida de saber si dos archivos son iguales en Unix / Linux?


Tengo un script de shell en el que necesito comprobar si dos archivos son iguales o no. Hago esto para muchos archivos, y en mi script el comando diff parece ser el cuello de botella de rendimiento.

Aquí está la línea:

diff -q $dst $new > /dev/null

if ($status) then ...

¿Podría haber una forma más rápida de comparar los archivos, tal vez un algoritmo personalizado en lugar del predeterminado diff?

Author: codeforester, 2012-10-15

5 answers

Creo que cmp se detendrá en la primera diferencia de bytes:

cmp --silent $old $new || echo "files are different"
 274
Author: Alex Howansky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-15 17:15:56

Me gusta @Alex Howansky he usado 'cmp silent silent' para esto. Pero necesito tanto una respuesta positiva como negativa, así que uso:

cmp --silent file1 file2 && echo '### SUCCESS: Files Are Identical! ###' || echo '### WARNING: Files Are Different! ###'

Entonces puedo ejecutar esto en la terminal o con un ssh para comprobar los archivos contra un archivo constante.

 36
Author: pn1 dude,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-23 00:29:48

¿Por qué no obtiene el hash del contenido de ambos archivos?

Pruebe este script, llámelo por ejemplo script.sh y luego ejecutarlo de la siguiente manera: script.sh file1.txt archivo2.txt

#!/bin/bash

file1=`md5 $1`
file2=`md5 $2`

if [ "$file1" = "$file2" ]
then
    echo "Files have the same content"
else
    echo "Files have NOT the same content"
fi
 16
Author: jabaldonedo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-25 17:14:43

Para los archivos que no son diferentes, cualquier método requerirá haber leído ambos archivos por completo, incluso si la lectura fue en el pasado.

No hay alternativa. Por lo tanto, crear hashes o sumas de comprobación en algún momento requiere leer todo el archivo. Los archivos grandes llevan tiempo.

La recuperación de metadatos de archivos es mucho más rápida que leer un archivo grande.

Entonces, ¿hay algún metadato de archivo que pueda usar para establecer que los archivos son diferentes? ¿Tamaño del archivo ? o incluso los resultados del archivo comando que solo lee una pequeña parte del archivo?

Tamaño del archivo Fragmento de código de ejemplo:

  ls -l $1 $2 | 
  awk 'NR==1{a=$5} NR==2{b=$5} 
       END{val=(a==b)?0 :1; exit( val) }'

[ $? -eq 0 ] && echo 'same' || echo 'different'  

Si los archivos son del mismo tamaño, entonces está atascado con lecturas completas de archivos.

 4
Author: jim mcnamara,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-15 18:38:15

Intente también usar el comando cksum:

chk1=`cksum <file1> | awk -F" " '{print $1}'`
chk2=`cksum <file2> | awk -F" " '{print $1}'`

if [ $chk1 -eq $chk2 ]
then
  echo "File is identical"
else
  echo "File is not identical"
fi

El comando cksum mostrará el número de bytes de un archivo. Véase "man cksum".

 2
Author: Nono Taps,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-23 00:59:59