Tengo un script de shell en el que necesito verificar si dos archivos contienen los mismos datos o no. Hago esto para muchos archivos, y en mi script el diff
comando parece ser el cuello de botella en el 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
?
diff
ycmp
.Respuestas:
Creo que
cmp
se detendrá en la primera diferencia de bytes:fuente
cmp -s $old $new
También funciona.-s
es la abreviatura de--silent
cmp
verificará primero el tamaño del archivo. Aquí está la versión de GNU, si desea ver las optimizaciones adicionales que incluye: git.savannah.gnu.org/cgit/diffutils.git/tree/src/cmp.cMe gusta @Alex Howansky he usado 'cmp --silent' para esto. Pero necesito respuestas positivas y negativas, así que uso:
Luego puedo ejecutar esto en la terminal o con un ssh para verificar los archivos contra un archivo constante.
fuente
echo success
comando (o cualquier otro comando que ponga en su lugar) falla, se ejecutará su comando de "respuesta negativa". Debe usar una construcción "if-then-else-fi". Por ejemplo, como este simple ejemplo .¿Por qué no obtienes el hash del contenido de ambos archivos?
Pruebe este script, llámelo por ejemplo script.sh y luego ejecútelo de la siguiente manera: script.sh file1.txt file2.txt
fuente
1/(2^511)
. A menos que le preocupe que alguien intente intencionalmente crear una colisión, la idea de que este método produzca un falso positivo no es realmente una preocupación seria.cmp
Sin embargo, es aún más eficiente, ya que no tiene que leer el archivo completo en el caso de que los archivos no coincidan.Debido a que apesta y no tengo suficientes puntos de reputación, no puedo agregar este dato como comentario.
Pero, si va a usar el
cmp
comando (y no necesita / quiere ser detallado), puede obtener el estado de salida. Por lacmp
página del manual:Entonces, podrías hacer algo como:
fuente
cmp --silent $FILE1 $FILE2 ; if [ "$?" == "1" ]; then echo "files differ"; fi
que a su vez es una forma más complicada de hacerlocmp --silent $FILE1 $FILE2 || echo "files differ"
porque puede usar el comando en la expresión directamente. Sustituye a$?
. Como resultado, se comparará el estado del comando existente. Y eso es lo que hace la otra respuesta. por cierto. Si alguien está luchando--silent
, no es compatible en todas partes (busybox). uso-s
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 verificació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 resultados del comando de archivo que solo lee una pequeña porción del archivo?
Fragmento de código de ejemplo de tamaño de archivo:
Si los archivos son del mismo tamaño, entonces está atascado con lecturas completas de archivos.
fuente
ls -n
para evitar problemas si los nombres de usuarios o grupos tienen espacios en blanco.Intente también usar el comando cksum:
El comando cksum generará el recuento de bytes de un archivo. Ver 'man cksum'.
fuente
md5
lee el archivo completo de todos modos, por lo tantocmp
, detenerse en la primera diferencia, será mucho más rápido.Haciendo algunas pruebas con un Raspberry Pi 3B + (estoy usando un sistema de archivos superpuestos y necesito sincronizar periódicamente), ejecuté una comparación propia para diff -q y cmp -s; tenga en cuenta que este es un registro desde adentro / dev / shm, por lo que las velocidades de acceso al disco no son un problema:
Lo corrí un par de veces. cmp -s siempre tuvo tiempos ligeramente más cortos en la caja de prueba que estaba usando. Entonces, si desea usar cmp -s para hacer cosas entre dos archivos ...
fuente