Compare diretórios enormes com o relatório de progresso

13

Acabei de sincronizar 2.000.000 arquivos (3 TB) de um RAID para outro.

Quero garantir que meus dados estejam intactos.

rsync -c leva muito tempo.

diff não me mostra o que está fazendo.

Existe uma alternativa que seja (a) mais rápida e (b) me mostre progresso enquanto estiver comparando?

(Estou no Mac e brew search diffme dá apgdiff colordiff diffstat diffutils fmdiff libxdiff open-vcdiff podiff rfcdiff vbindiff bsdiff diffpdf diffuse dwdiff kdiff3 ndiff perceptualdiff rdiff-backup tkdiff wdiff ... um deles faria o trabalho?)

Dan
fonte
Também estou confuso sobre o motivo pelo qual rsyncos dados foram copiados em torno de 150MB / s, mas diffcomparam em apenas 60MB / s ...?
Dan
1
A cópia usada rsyncé mais rápida b / c, rsyncpor padrão, não usa somas de verificação para comparar arquivos, ele analisa informações de tamanho e data. Quando você usa rsync -ctodos os arquivos, é necessário calcular as somas de verificação, o que é uma tarefa onerosa, portanto, por que não é o padrão.
slm
Sim, mas o diff não copia ... apenas lê os dois arquivos; enquanto o rsync, para copiar, deve ler cada byte e depois escrever. Como era um rsync do zero, copiava todos os arquivos.
Dan

Respostas:

6

editar para correção e clareza das opções - esqueci '--brief'

diff -rs --brief "$dir1" "$dir2" 

-r, --recursive              recursively compare any subdirectories found
-s, --report-identical-files report when two files are the same
-q, --brief                  report only when files differ
--speed-large-files      assume large files and many scattered small changes

e adicione outras opções a gosto, dependendo do que você está comparando:

-i, --ignore-case            ignore case differences in file contents
-b, --ignore-space-change    ignore changes in the amount of white space
-B, --ignore-blank-lines     ignore changes whose lines are all blank
--strip-trailing-cr      strip trailing carriage return on input
--ignore-file-name-case  ignore case when comparing file names

O diff -rs lerá todos os bytes do original e copiará e reportará os arquivos iguais.

O formato de saída diff é definido pelo POSIX, por isso é bastante portátil. Você pode adicionar algo como:

| tee diff-out.1 | grep -v -E '' Arquivos. * e. * são idênticos '

Você pode usar chksums ou hashes, mas é necessário mantê-los sincronizados com as árvores de arquivos, para voltar a ler todos os bytes de cada arquivo.

EDIT - muito tempo para ser um comentário, em resposta a:

arquivos com mais de 10 GB não estão verificando

Você pode tentar esta opção diff: --speed-large-files

É possível que o diff que você está usando não esteja lidando bem com arquivos muito grandes (maiores que a memória do sistema, por exemplo) e, portanto, esteja relatando diferenças entre os arquivos que são realmente iguais.

Eu pensei que havia uma opção -h ou um 'bdiff' que se saía melhor em arquivos grandes, mas não consigo encontrar um no Fedora. Acredito que as opções --speed-large-files são sucessoras de uma opção '-h' "comparação sem entusiasmo".

Uma abordagem diferente seria repetir o comando rsync que você usou, com '-vin' (verbose, itemize, no_run). Isso reportaria quaisquer diferenças encontradas pelo rsync - e não deveria haver nenhuma.

Para mover alguns arquivos, você está vendo um script como:

if [ cmp -s "$dir1/$path" "$dir2/$path" ] ; then 
target="$dir2/verified/$path"
mkdir -p $(basename "$target")
mv  "$dir2/$path" "$target"
fi

mas eu não recomendo fazer isso. A questão subjacente é "como posso ter certeza de que o rsync copiou corretamente uma hierarquia de arquivos?" e se você puder demonstrar para si mesmo que o rsync está funcionando bem, com diff ou alguma outra ferramenta, basta confiar no rsync, em vez de contorná-lo.

O rsync -vin será comparado com qualquer outra opção que você escolher. Eu pensei que era padrão a soma de verificação, mas você está certo, -c ou --checksum é necessário para isso.

O utilitário diff é realmente destinado a arquivos de linhas de texto, mas deve reportar sub-idênticos 'idênticos' para arquivos binários.

O --brief deve suprimir qualquer saída de conteúdo do arquivo - minhas desculpas por ignorá-lo mais cedo - foi semi-enterrado em um script feio.

D McKeon
fonte
Existe uma maneira de obtê-lo para mvtodos os arquivos encontrados em uma pasta "verificada" na raiz da unidade, preservando o caminho completo? Por exemplo, se /disk1/a/b/c/file1for idêntico a /disk2/a/b/c/file1, então mova para /disk1/verified/a/b/c/file1. Então eu poderia acabar apenas com os arquivos mal copiados. (Até agora lotes de arquivos mais de 10 GB não são a verificação, o que é assustador.)
Dan
Você pode tentar esta opção: --speed-large-files
D McKeon
O que isso faz exatamente?
Dan
Se eu executar rsync -vin- isso faz uma comparação byte a byte ou soma de verificação? Eu pensei que o rsync apenas comparava tamanho / data, a menos que você adicionasse -c. E pelo que li, speed large filesparece que só faz diferença com arquivos não binários ... ou estou errado?
Dan
diffme dá resultados na forma de "Files __ and ___ differ"... e estou executando isso sed -e "s/Files /cp -afv /" -e "s/ and / /" -e "s/ differ$//"para tentar gerar um script para copiar novamente os arquivos defeituosos. Mas a saída do diff não é citada, portanto não funciona. Posso obtê-lo para fornecer caminhos citados?
Dan
4

Aqui está diffo relatório de progresso com base na contagem de arquivos:

diff -rqs dir1 dir2 | pv -l -s filecount > logfile

Você precisará de pv (visualizador de tubos): http://www.ivarch.com/programs/pv.shtml

Explicação:

  • diff -r compare diretório e subdiretórios recursivamente.
  • diff -qimprimir apenas nomes de arquivos diferentes. não imprima diferenças reais.
  • diff -simprima também nomes de arquivos de arquivos que não diferem. isso é importante para as informações de progresso.
  • pv -l relatar o progresso com base na contagem de linhas.
  • pv -s count estimar o tempo para concluir com base na contagem.
  • O redirecionamento para logfileé para uma saída bonita. Caso contrário, a saída de diffserá combinada com a linha de status de pv.

para obter a contagem de arquivos, use o seguinte comando:

find dir1 -type f | wc -l

Filtre o arquivo de log para arquivos diferentes:

grep -v "^Files .* identical$" logfile

Essa variação imprimirá arquivos diferentes em tempo real e também fará o logon de tudo logfile:

diff -rqs dir1 dir2 | pv -l -s filecount | 
    tee logfile | grep -v "^Files .* identical$"

Como alternativa, você pode registrar apenas arquivos diferentes:

diff -rqs dir1 dir2 | pv -l -s filecount | 
    grep -v "^Files .* identical$" > logfile

Nota: os comandos acima relatam o progresso com base na contagem de arquivos. Isso funciona melhor se houver muitos arquivos pequenos. Se você tiver alguns arquivos enormes, não se divertirá muito com isso.

Infelizmente, não conheço uma maneira fácil de relatar o progresso com base nos bytes comparados.


Se você puder encontrar sua paz apenas comparando os metadados (e não o conteúdo real dos arquivos), poderá usar o rsync. Isso será consideravelmente mais rápido.

Para mais detalhes:

lesmana
fonte
0

Eu usaria algum tipo de aplicativo hash para verificar a integridade dos dados. Eu sei que muitos utilitários de localização de arquivos duplicados usam hashes para identificar duplicados / não duplicados. Parece-me que esta é uma investigação que pode valer a pena.

Codificador OT
fonte
0

Você pode usar o rdiff-backup para isso. Instale-o nos dois servidores e fará comparações inteligentes de somas de verificação e sincronizará o que ainda não está lá.

Timo
fonte