Hash um arquivo em blocos de 64 MB?

Hash um arquivo em blocos de 64 MB?

Eu tenho um arquivo muito grande (200 GB). Aparentemente, quando eu o transferi, ele não copiou corretamente. O hash sha1 em ambos é diferente. Existe uma maneira de dividir o arquivo em blocos (como 1 MB ou 64 MB) e gerar um hash para cada bloco? Então compare/corrija?

Talvez eu simplesmente escreva um aplicativo rápido para fazer isso.

Responder1

Esse “aplicativo rápido” já existe e é relativamente comum: rsync. Claro, o rsync fará muito mais do que isso, mas o que você quer é bastante simples:

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

Por padrão, isso usará ssh (ou talvez rsh, em uma versão muito antiga) para fazer a conexão e transferir os dados. Outros métodos também são possíveis.

As opções que passei são:

  • -c- pule com base nas somas de verificação, não no tamanho do arquivo/mtime. Por padrão, o rsync otimiza e ignora transferências onde o tamanho e o tempo correspondem. -cforça-o a calcular a soma de verificação (que é uma operação cara, em termos de E/S). Observe que esta é uma soma de verificação baseada em bloco (a menos que você diga para fazer apenas arquivos inteiros) e só transferirá os blocos corrompidos. O tamanho do bloco é escolhido automaticamente, mas pode ser substituído -B(duvido que haja algum motivo para isso).
  • -v— detalhado, dará alguns detalhes (em qual arquivo está trabalhando)
  • -P— ativa ambos os arquivos parciais (para que, se chegar na metade, não atrapalhe o trabalho) e uma barra de progresso.
  • --inplace— Atualize o arquivo existente, não um arquivo temporário (que substituiria o arquivo original). Evita que você tenha um arquivo temporário de 200 GB. Também implica arquivos parciais, o que -Pé parcialmente redundante.

A propósito: não tenho certeza de como você fez a transferência original, mas se foi sftp/scp, então algo está muito errado - eles protegem totalmente contra qualquer corrupção na rede. Você realmente deveria rastrear a causa. RAM defeituosa é relativamente comum.

Responder2

Se você quiser transferir novamente o arquivo para outra máquina através de uma conexão de rede,usar rsync.

Se quiser ter uma ideia de onde estão as diferenças, o jeito mais fácil seria ter as duas versões na mesma máquina. Se você não quiser fazer isso porque a largura de banda é muito cara, aqui estão algumas maneiras de verificar pedaços de arquivos.

Este método depende de head -cdeixar a posição do arquivo onde parou e pré-calcular o tamanho para saber onde terminar o loop.

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 depende de head -cdeixar a posição do arquivo onde parou e usa cksumpara encontrar o tamanho de cada pedaço (um pedaço curto indica o final do arquivo).

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 chama ddpara pular para a posição inicial desejada para cada pedaço.

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

Responder3

Você provavelmente deveria olhar para split:

Aqui está a página de manual com exemplos:

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

informação relacionada