Eu tenho um script de shell no qual preciso verificar se dois arquivos contêm os mesmos dados ou não. Faço isso para muitos arquivos e, no meu script, o diff
comando parece ser o gargalo de desempenho.
Aqui está a linha:
diff -q $dst $new > /dev/null
if ($status) then ...
Poderia haver uma maneira mais rápida de comparar os arquivos, talvez um algoritmo personalizado em vez do padrão diff
?
diff
ecmp
.Respostas:
Acredito que
cmp
irá parar na primeira diferença de bytes:fonte
cmp -s $old $new
também funciona.-s
é curto para--silent
cmp
irá verificar primeiro o tamanho do arquivo. Aqui está a versão GNU, se você quiser ver as otimizações adicionais que inclui: git.savannah.gnu.org/cgit/diffutils.git/tree/src/cmp.cEu gosto de @Alex Howansky ter usado 'cmp --silent' para isso. Mas eu preciso de respostas positivas e negativas, então eu uso:
Posso então executar isso no terminal ou com um ssh para verificar os arquivos em um arquivo constante.
fonte
echo success
comando (ou qualquer outro comando que você colocar no lugar) falhar, o comando "resposta negativa" será executado. Você deve usar uma construção "if-then-else-fi". Por exemplo, como este exemplo simples .Por que você não obtém o hash do conteúdo dos dois arquivos?
Experimente esse script, chame-o, por exemplo, script.sh e execute-o da seguinte maneira: script.sh file1.txt file2.txt
fonte
1/(2^511)
. A menos que você esteja preocupado com alguém tentando intencionalmente criar uma colisão, a idéia desse método produzindo um falso positivo não é realmente uma preocupação séria.cmp
ainda é mais eficiente, pois não precisa ler o arquivo inteiro no caso em que os arquivos não coincidem.Como sou péssima e não tenho pontos de reputação suficientes, não posso adicionar esse detalhe como comentário.
Mas, se você for usar o
cmp
comando (e não precisar / quiser ser detalhado), basta pegar o status de saída. Pelacmp
página do manual:Então, você poderia fazer algo como:
fonte
cmp --silent $FILE1 $FILE2 ; if [ "$?" == "1" ]; then echo "files differ"; fi
que por sua vez é uma maneira mais complicada de fazer,cmp --silent $FILE1 $FILE2 || echo "files differ"
porque você pode usar o comando na expressão diretamente. Substitui por$?
. Como resultado, o status existente do comando será comparado. E é isso que a outra resposta faz. btw. Se alguém está enfrentando problemas--silent
, ele não é suportado em qualquer lugar (busybox). use-s
Para arquivos que não são diferentes, qualquer método exigirá a leitura completa dos dois arquivos, mesmo que a leitura tenha sido no passado.
Não ha alternativa. Portanto, criar hashes ou somas de verificação em algum momento requer a leitura de todo o arquivo. Arquivos grandes levam tempo.
A recuperação de metadados do arquivo é muito mais rápida que a leitura de um arquivo grande.
Portanto, existem metadados de arquivo que você pode usar para estabelecer que os arquivos são diferentes? Tamanho do arquivo ? ou até mesmo resultados do comando file, que lê apenas uma pequena parte do arquivo?
Fragmento de código de exemplo de tamanho de arquivo:
Se os arquivos forem do mesmo tamanho, você ficará com as leituras completas do arquivo.
fonte
ls -n
para evitar problemas se os nomes de usuários ou grupos tiverem espaços em branco.Tente também usar o comando cksum:
O comando cksum produzirá a contagem de bytes de um arquivo. Veja 'man cksum'.
fonte
md5
lê o arquivo inteiro de qualquer maneira, entãocmp
, parar na primeira diferença será muito mais rápido.Fazendo alguns testes com um Raspberry Pi 3B + (estou usando um sistema de arquivos de sobreposição e preciso sincronizar periodicamente), fiz uma comparação própria para diff -q e cmp -s; observe que este é um log de dentro de / dev / shm, portanto a velocidade de acesso ao disco não é um problema:
Eu o executei algumas vezes. O cmp -s consistentemente teve tempos um pouco mais curtos na caixa de teste que eu estava usando. Então, se você quiser usar cmp -s para fazer coisas entre dois arquivos ...
fonte