¿Hash un archivo por bloques de 64 MB?

¿Hash un archivo por bloques de 64 MB?

Tengo un archivo muy grande (200 GB). Aparentemente, cuando lo transfirí no se copió correctamente. El hash sha1 en ambos es diferente. ¿Hay alguna manera de dividir el archivo en bloques (como 1 MB o 64 MB) y generar un hash para cada bloque? ¿Entonces comparar/arreglar?

Podría escribir una aplicación rápida para hacerlo.

Respuesta1

Esa "aplicación rápida" ya existe y es relativamente común: rsync. Por supuesto, rsync hará mucho más que eso, pero lo que quieres es bastante simple:

rsync -cvP --inplace user@source:src-path-to-file dest-path-to-file   # from the destination
rsync -cvP --inplace src-path-to-file user@dest:dest-path-to-file     # from the source

De forma predeterminada, usará ssh (o tal vez rsh, en una versión muy antigua) para realizar la conexión y transferir los datos. También son posibles otros métodos.

Las opciones que pasé son:

  • -c— omitir según las sumas de verificación, no el tamaño del archivo/mtime. De forma predeterminada, rsync optimiza y omite las transferencias cuando el tamaño y el tiempo coinciden. -clo obliga a calcular la suma de verificación (que es una operación costosa, en términos de E/S). Tenga en cuenta que esta es una suma de verificación basada en bloques (a menos que le indique que solo haga archivos completos) y solo transferirá los bloques corruptos. El tamaño del bloque se elige automáticamente, pero se puede anular -B(dudo que haya algún motivo para hacerlo).
  • -v— detallado, dará algunos detalles (en qué archivo está trabajando)
  • -P— activa ambos archivos parciales (de modo que si llega a la mitad, no descartará el trabajo) y una barra de progreso.
  • --inplace— Actualice el archivo existente, no un archivo temporal (que luego reemplazaría el archivo original). Le evita tener un archivo temporal de 200 GB. También implica archivos parciales, por lo que -Pes parcialmente redundante.

Por cierto: no estoy seguro de cómo hiciste la transferencia original, pero si fue sftp/scp, entonces algo anda muy mal: protegen completamente contra cualquier corrupción en la red. Realmente deberías rastrear la causa. La RAM defectuosa es relativamente común.

Respuesta2

Si desea volver a transferir el archivo a otra máquina a través de una conexión de red,usar rsync.

Si quieres tener una idea de dónde están las diferencias, la forma más sencilla sería tener las dos versiones en la misma máquina. Si no desea hacerlo porque el ancho de banda es demasiado costoso, aquí le presentamos formas de verificar fragmentos de archivos.

Este método se basa en head -cdejar la posición del archivo donde lo dejó y calcula previamente el tamaño para saber dónde finalizar el bucle.

n=$(($(wc -c <very_large_file) / (64*1024*1024) + 1))
i=0
while [ $i -gt $n ]; do
    head -c 64m | sha256sum
    i=$((i+1))
done <very_large_file

Este método se basa en head -cdejar la posición del archivo donde lo dejó y se utiliza cksumpara encontrar el tamaño de cada fragmento (un fragmento corto indica el final del archivo).

while true; do
    output=$(head -c 64m | cksum)
    size=${output#* }; size=${output%% *}
    if [ $size -eq 0 ]; then break; fi
    echo "$output"
done <very_large_file

Este método llama dda saltar a la posición inicial deseada para cada fragmento.

n=$(($(wc -c <very_large_file) / (64*1024*1024) + 1))
i=0
while [ $i -gt $n ]; do
    dd if=very_large_file ibs=64m skip=$i count=1 | sha256sum
    i=$((i+1))
done <very_large_file

Respuesta3

Probablemente deberías mirar split:

Aquí está la página de manual con ejemplos:

https://ss64.com/bash/split.html

información relacionada