Existe MD5 (ou similar) para uma pasta? Como verificar se duas pastas são iguais?

10

Eu gostaria de encontrar um md5sum(ou cálculo semelhante) de uma pasta sem compactá-la em um arquivo.

Por exemplo, se na pasta MyFolderque tem os arquivos 1.txt, 2.txte 3.txt, contendo:


1.txt

O texto em 1.txt

2.txt

O texto em 2.txt

3.txt

O texto em 3.txt


Como posso calcular o valor md5suminteiro MyFolder? Há algum caminho? Quero usar isso para verificar se duas pastas têm o mesmo conteúdo.

Isso pode ser útil para verificar se dois CDs ou pastas são iguais. Eu gostaria de uma maneira fácil de fazer isso.

GarouDan
fonte

Respostas:

15

A ferramenta md5deep foi desenvolvida exatamente para esse fim. Muitas distribuições Linux o oferecem em forma de pacote.

David Schwartz
fonte
1
Valeu! Funcionou bem para mim. Para outros usuários com o mesmo problema para gostar deste: sudo apt-get install md5deep md5deep -rel /path/to/your/directory/ > directory_hash.md5 md5deep -X directory_hash.md5 -r /path/to/your/second/direcotory Thx muito.
GarouDan
@GarouDan. O comando que você mostrou seguirá links simbólicos. Você pode usar a -oopção para manipular tipos de arquivos.
Peter.O
Oh thx ... não sei disso ... realmente útil. Lembrarei!
GarouDan
4

Se você não quiser arquivá-lo, talvez possa fazer algo assim

diff <(find folder1) <(find folder2)

Pode ser necessário adaptar os findcomandos para ser mais preciso.

EDIT Você pode adicionar -execà sua chamada de busca para comparar o conteúdo dos arquivos. Algo semelhante a isso:

diff <(find folder1 -type f -exec md5sum {} \; | sort) <(find folder2 -type f -exec md5sum {} \; | sort)

Lembre-se de que você pode adaptar isso.

rahmu
fonte
É um ponto interessante. Isso lista todos os arquivos de cada pasta ... mas se eu tiver uma quantidade realmente grande de arquivos ... como verificar se existem os mesmos arquivos (com os dados - talvez usando uma ferramenta md5sum) em cada pasta?
GarouDan
1
Em seguida, faça uma comparação da saída MD5SUM de cada arquivo. Você só precisa encadear os comandos find, md5sum e diff de maneira diferente.
sybreon
Thx sobre suas idéias também, cya ... vou tentar coisas interessantes com estes encontrar comando depois de ... obrigado.
GarouDan
3

Uma maneira de testar poderia ser gerar um md5sum com base na concatenação de todos os arquivos na pasta e suas subpastas. Lembre-se de que isso também requer que os arquivos tenham os mesmos nomes (pois devem estar na mesma ordem de classificação). O seguinte código deve funcionar:

#!/bin/bash

shopt -s nullglob
shopt -s globstar || { printf '%s\n' 'Bash 4 is required for globstar.' ; exit 1 ; }
(( $# == 2 )) || { printf '%s\n' "Usage: ${0##*/} olddir newdir" ; exit 2 ; }

for _file in "$1"/**/*; do [[ -f ${_file} && ! -L ${_file} ]] && _files_in_old_dir+=( "${_file}" ); done
for _file in "$2"/**/*; do [[ -f ${_file} && ! -L ${_file} ]] && _files_in_new_dir+=( "${_file}" ); done

(( ${#_files_in_old_dir[@]} )) || { printf '%s\n' 'No files in old dir.' ; exit 3 ; }
(( ${#_files_in_new_dir[@]} )) || { printf '%s\n' 'No files in new dir.' ; exit 4 ; }

_md5_old_dir=$(cat "${_files_in_old_dir[@]}" | md5sum)
_md5_new_dir=$(cat "${_files_in_new_dir[@]}" | md5sum)

{ [[ ${_md5_old_dir} == "${_md5_new_dir}" ]] && (( ${#_files_in_old_dir[@]} == ${#_files_in_new_dir[@]} )) ; } && printf '%s\n' 'Folders are identical.' || { printf '%s\n' 'Folders are not identical.' ; exit 3 ; }

Se você realmente se importa com os nomes de arquivos, etc, pode usar um loop para comparar o que está em ${_files_in_old_dir}e ${_files_in_new_dir}. Isso deve funcionar na maioria dos casos (pelo menos verifica o número de arquivos no diretório e seus subdiretórios).

Chris Down
fonte
Esse é um bom roteiro ... thx @Chris. Mas tem um problema ... usando cat , subpastas trava com erros ... Você tem uma idéia para resolvê-lo? Muito obrigado.
GarouDan
Isso funciona bem para mim. Verifique se o seu shell suporta globstar. Qual é o erro?
Chris Baixo
1
Ele "funciona" (+1) ... mas o globstar no bash 4 segue links simbólicos de diretório , mas isso é apenas um problema se um dos diretórios contiver um link simbólico.
Peter.O
@fered Boa ligação, adicionei em um teste.
Chris Baixo
0

Percebi que a postagem original é bastante antiga, no entanto, acho que essas informações ainda podem ser valiosas para quem procura uma solução para verificar se os arquivos foram copiados corretamente. O Rsync pode ser o melhor método para copiar dados e as respostas fornecidas neste segmento são boas; no entanto, para aqueles que não são experientes no Linux, tentarei dar uma explicação mais detalhada.

Cenário: você acabou de copiar dados de um disco para outro, com muitos subdiretórios e arquivos. Você deseja verificar se todos os dados foram copiados corretamente.

Primeiro verifique se md5deep está instalado, emitindo o comando md5deep -v.

Se você receber uma mensagem dizendo algo como 'comando não encontrado', instale o md5deep por apt-get install md5deep.

Supõe-se que você deseja apenas lidar com arquivos regulares. Se você deseja lidar com outros tipos de arquivos, consulte o sinalizador -o no manual md5deep. ( man md5deep)

Agora você está pronto e assumimos que você copiou os arquivos de /mnt/orginalpara /mnt/backup, substitua-os pelos diretórios que estiver usando.

Primeira alteração no diretório de origem, esta é a fonte original dos arquivos que você copiou ou fez backup:

cd /mnt/orginal

Em seguida, faça uma soma de verificação de cada arquivo:

md5deep -rel -o f . >> /tmp/checksums.md5

Este comando explicou:

-r ativa o modo recursivo

-e exibe indicador de progresso

-l ativa caminhos de arquivo relativos.

-o f funciona apenas em arquivos regulares (não em dispositivos de bloco, pipes nomeados etc.)

. informa ao md5deep para iniciar no diretório atual.

>> /tmp/checksums.md5diz ao md5deep para redirecionar toda a saída para /tmp/checksums.md5.

Observe que, se você deseja sobrescrever o conteúdo nas versões anteriores /tmp/checksums.md5, use >e não>>

Observe que esse comando pode demorar um pouco, dependendo da velocidade io e do tamanho dos dados. Você pode experimentar o nice e / ou ionice para aumentar o desempenho do md5deep, mas isso está fora do escopo desta resposta.

Quando a criação das somas de verificação estiver concluída, você terá um arquivo com entradas semelhantes a:

69c0a826b29c8f40b7ca5e56e53d7f83 ./oldconfig-11-09-2013/etc2/apm/event.d/20hdparm 651f3c7f79a14332f9fa7bb368039210 ./oldconfig-11-09-201-2013/etc2/apm/event.d/an-9-09684201. /etc2/apm/scripts.d/alsa e9b9131660a8013983bc5e19d7d669eb ./oldconfig-11-09-2013/etc2/ld.so.cache

A primeira coluna é a soma de verificação do md5 e a segunda coluna é o caminho relativo para o arquivo ao qual a soma de verificação pertence.

Se você deseja ver quantos arquivos existem no arquivo de soma de verificação, emita o comando:

wc /tmp/checksums.md5 -l

Agora, você deseja verificar se os dados copiados estão corretos:

cd /mnt/backup

md5deep -o f -reX /tmp/checksums.md5 . >> /tmp/compare.result

A única diferença de quando criamos as somas de verificação é -X, que exibe o hash atual de um arquivo se a entrada no arquivo checksums.md5 não corresponder. Portanto, no final do teste, se /tmp/compare.resultestiver em branco, você poderá confiar que todos os arquivos serão copiados corretamente, pois as somas de verificação correspondem.

Observe que apenas os arquivos listados no /tmp/checksums.md5arquivo serão verificados quanto a uma soma de verificação correta; se houver algum arquivo adicional no /mnt/backupdiretório, o md5deep não notificará você sobre eles.

Notas:

  • Você não precisa necessariamente usar o redirecionamento para armazenar arquivos de saída. Consulte o manual do md5deep para obter mais informações.

  • Pode ser necessário executar os comandos md5deep como root, dependendo das permissões dos arquivos que você está manipulando.

NordicViking
fonte
0

Se você deseja verificar recursivamente as diferenças entre dois diretórios /path1e /path2 sem usar md5deep:

diff <(cd /path1 && find . -type f |xargs md5) <(cd /path2 && find . -type f |xargs md5)

Explicação:

  • entrou path1para fazer todas as linhas impressas por findserem relativas a path1( cd /path1)
  • lista todos os arquivos recursivamente no caminho atual ( && find . -type f)
  • use cada saída de linha findcomo entrada para md5( | xargs md5)

A saída ficará assim se houver alguma diferença:

< MD5 (./index.html) = 36b01762f0329b2c12a5186520c7d78a
< MD5 (./inline.js) = ce99823a4b2c24839a727c5781f59a36
< MD5 (./main.js) = 3a597404d3ba7f0a6e3cb093ef57ebb2
---
> MD5 (./index.html) = 3a3d7663a7b2871ff37b9081a53593f9
> MD5 (./inline.js) = 1bbd0ecfc75b578413105c6b9009f9b3
> MD5 (./main.js) = 0f44abe5084add3cabdc39feec0c699878c78
david_p
fonte