Como posso calcular uma soma de verificação md5 de um diretório?
Pergunta
Eu preciso calcular uma soma de verificação md5 resumo para todos os arquivos de um determinado tipo (*.py
por exemplo) colocado sob um diretório e todos os sub-diretórios.
Qual é a melhor maneira de fazer isso?
Editar: As soluções propostas são muito agradáveis, mas isso não é exatamente o que eu preciso. Estou à procura de uma solução para obter um resumo única soma de verificação que irá identificar exclusivamente o diretório como um todo -. Incluindo o conteúdo de todos os seus sub-diretórios
Solução
find /path/to/dir/ -type f -name "*.py" -exec md5sum {} + | awk '{print $1}' | sort | md5sum
O comando listas de encontrar todos os arquivos que terminam em .py. O md5sum é calculado para cada arquivo .py. awk é usado para apanhar os md5sums (ignorando os nomes de ficheiros, os quais podem não ser exclusivas). Os md5sums são classificadas. O md5sum desta lista ordenada é então devolvido.
Eu testei isso copiando um diretório de teste:
rsync -a ~/pybin/ ~/pybin2/
Eu renomeado alguns dos arquivos em ~ / pybin2.
O comando find...md5sum
retorna a mesma saída para ambos os diretórios.
2bcf49a4d19ef9abd284311108d626f1 -
Outras dicas
Crie um arquivo tar na mosca e tubo que a md5sum
:
tar c dir | md5sum
Isso produz um único md5sum que deve ser exclusivo para a sua configuração de arquivos e sub-diretórios. Nenhum arquivo é criado no disco.
sugestão de usar tar c <dir>
das ire_and_curses tem alguns problemas:
- tar processa entradas de diretório na ordem que eles são armazenados no sistema de arquivos, e não há maneira de mudar esta ordem. Isso efetivamente pode produzir resultados completamente diferentes se você tem o "mesmo" diretório em lugares diferentes, e eu sei que não há maneira de corrigir isso (alcatrão não pode "sort" seus arquivos de entrada em uma ordem específica).
- I geralmente se preocupam se os números GROUPID e OwnerID são as mesmas, não necessariamente se a representação de cadeia de grupo / proprietário são os mesmos. Isto está em linha com o que por exemplo
rsync -a --delete
faz: ele sincroniza praticamente tudo (menos xattrs e ACLs), mas ele irá sincronizar o proprietário eo grupo com base em sua ID, e não em representação da cadeia. Então, se você sincronizado com um sistema diferente que não tem necessariamente os mesmos usuários / grupos, você deve adicionar a bandeira--numeric-owner
para tar - tar irá incluir o nome do arquivo do diretório que você está verificando-se, apenas algo a ter em conta.
Enquanto não há solução para o primeiro problema (ou a menos que você tem certeza de que não afeta você), eu não iria usar essa abordagem.
As soluções find
base acima propostas também não são boas, porque eles só incluem arquivos, não diretórios, que se torna um problema se você o checksumming deve ter em mente diretórios vazios.
Finalmente, soluções mais sugeridas não são classificadas de forma consistente, porque o agrupamento pode ser diferente entre os sistemas.
Esta é a solução que eu vim com:
dir=<mydir>; (find "$dir" -type f -exec md5sum {} +; find "$dir" -type d) | LC_ALL=C sort | md5sum
Notas sobre esta solução:
- O
LC_ALL=C
é assegurar ordem de classificação confiável em sistemas - Este não diferenciar entre um diretório "chamado \ nwithanewline" e dois diretórios "nome" e "withanewline", mas a chance de que ocorrendo parece muito improvável. Um geralmente corrige isso com uma bandeira
-print0
parafind
mas desde que há outras coisas acontecendo aqui, eu só posso ver soluções que tornam o comando mais complicado, então vale a pena.
PS: um dos meus sistemas usa um find
busybox limitada que não suporta -exec
nem -print0
bandeiras, e também ele acrescenta '/' para denotar diretórios, enquanto findutils encontrar não parece, portanto, para esta máquina que eu preciso execute:
dir=<mydir>; (find "$dir" -type f | while read f; do md5sum "$f"; done; find "$dir" -type d | sed 's#/$##') | LC_ALL=C sort | md5sum
Felizmente, não tenho arquivos / diretórios com novas linhas em seus nomes, de modo que este não é um problema no sistema.
Se você só se preocupam com arquivos e diretórios não vazios, isso funciona muito bem:
find /path -type f | sort -u | xargs cat | md5sum
Por uma questão de exaustividade, há md5deep (1) ; não é directamente aplicável devido à * exigência filtro .py, mas deve fazer muito bem em conjunto com find (1).
A solução que funcionou melhor para mim:
find "$path" -type f -print0 | sort -z | xargs -r0 md5sum | md5sum
A razão por que funcionou melhor para mim:
- nomes de arquivo alças que contenham espaços
- ignora sistema de arquivos meta-dados
- Detecta se o arquivo foi renomeado
Problemas com outras respostas:
Filesystem meta-dados não é ignorado para:
tar c - "$path" | md5sum
Não lidar com nomes de arquivos que contenham espaços, nem detecta se o arquivo foi renomeado:
find /path -type f | sort -u | xargs cat | md5sum
Se você quiser um md5sum abrangendo todo o diretório, eu faria algo assim
cat *.py | md5sum
soma de verificação de todos os arquivos, incluindo o conteúdo e os nomes de arquivo
grep -ar -e . /your/dir | md5sum | cut -c-32
O mesmo que acima, mas apenas incluindo arquivos * .py
grep -ar -e . --include="*.py" /your/dir | md5sum | cut -c-32
Você também pode seguir links simbólicos, se você quiser
grep -aR -e . /your/dir | md5sum | cut -c-32
Outras opções que você pode considerar o uso com grep
-s, --no-messages suppress error messages
-D, --devices=ACTION how to handle devices, FIFOs and sockets;
-Z, --null print 0 byte after FILE name
-U, --binary do not strip CR characters at EOL (MSDOS/Windows)
GNU find
find /path -type f -name "*.py" -exec md5sum "{}" +;
Tecnicamente, você só precisa executar ls -lR *.py | md5sum
. A menos que você está preocupado com alguém modificar os arquivos e tocá-los de volta para suas datas originais e nunca alterar os tamanhos dos arquivos, a saída do ls
deve dizer se o arquivo foi alterado. Meu unix-foo é fraca, então você pode precisar de alguns parâmetros mais de linha de comando para obter o tempo e tempo de modificação para imprimir criar. ls
também lhe dirá se as permissões sobre os arquivos mudaram (e estou certo de que há interruptores para desligar isso se você não se preocupam com isso).
Eu uso HashCopy para fazer isso. Ele pode gerar e verificar MD5 e SHA em um único arquivo ou um diretório. Ele pode ser baixado a partir www.jdxsoftware.org.
Usando md5deep
:
md5deep -r FOLDER | awk '{print $1}' | sort | md5sum
Eu tive o mesmo problema, então eu vim com esse script que apenas lista os md5sums dos arquivos no diretório e, se encontrar um subdiretório ele é executado novamente a partir de lá, para que isso aconteça o script tem que ser capaz de executar através do diretório atual ou de um subdiretório, se disse que o argumento é passado em $ 1
#!/bin/bash
if [ -z "$1" ] ; then
# loop in current dir
ls | while read line; do
ecriv=`pwd`"/"$line
if [ -f $ecriv ] ; then
md5sum "$ecriv"
elif [ -d $ecriv ] ; then
sh myScript "$line" # call this script again
fi
done
else # if a directory is specified in argument $1
ls "$1" | while read line; do
ecriv=`pwd`"/$1/"$line
if [ -f $ecriv ] ; then
md5sum "$ecriv"
elif [ -d $ecriv ] ; then
sh myScript "$line"
fi
done
fi
Se você quiser realmente a independência dos atributos do sistema de arquivos e das diferenças de nível de bit de algumas versões de alcatrão, você poderia usar cpio:
cpio -i -e theDirname | md5sum
Há mais duas soluções:
Criar:
du -csxb /path | md5sum > file
ls -alR -I dev -I run -I sys -I tmp -I proc /path | md5sum > /tmp/file
Verifique:
du -csxb /path | md5sum -c file
ls -alR -I dev -I run -I sys -I tmp -I proc /path | md5sum -c /tmp/file
md5sum
funcionou bem para mim, mas eu tinha problemas com sort
e classificar nomes de arquivo. Então, ao invés eu classificado por resultado md5sum
. Eu também precisava de excluir alguns arquivos, a fim de criar resultados comparáveis.
find . -type f -print0 \
| xargs -r0 md5sum \
| grep -v ".env" \
| grep -v "vendor/autoload.php" \
| grep -v "vendor/composer/" \
| sort -d \
| md5sum