
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.-c
forç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 -c
deixar 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 -c
deixar a posição do arquivo onde parou e usa cksum
para 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 dd
para 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: