sha1sum para um diretório de diretórios


33
sha1sum ./path/to/directory/* | sha1sum 

o acima foi postado como uma maneira de calcular um sha1sum de um diretório que contém arquivos. Este comando falhará se o diretório incluir mais diretórios. Existe uma maneira de calcular recursivamente o sha1sum de um diretório de diretórios universalmente (sem o ajuste personalizado de um algoritmo para o diretório específico em questão)?

Respostas:


14

Graças a este post SO -

find . -type f \( -exec sha1sum "$PWD"/{} \; \) | sha1sum

Aviso: este código não foi testado ! Edite esta pergunta se estiver errada e você pode corrigi-la; Eu aprovarei sua edição.


Desculpe; Eu não pude resistir! ;-) A recursão é divertida. Claro que há um caminho. Vou escrever uma resposta adequada agora.
allquixotic

3
Isso não gera o mesmo hash para exatamente as mesmas pastas nas máquinas diferentes, porque a saída também contém <hash> e <caminho do arquivo>, que é diferente em máquinas diferentes e causa hash diferente em máquinas diferentes. A linha correta deve ser como find . -type f \( -exec sha1sum "$PWD"/{} \; \) | awk '{print $1}' | sort | sha1sum@allquixotic
alper

11
Além disso, os hashes de arquivos devem ser ordenados, o que também causará hashes diferentes se a ordem de classificação for diferente em máquinas diferentes.
#

40

Eu geralmente gosto do padrão "find | xargs", assim:

find ./path/to/directory/ -type f -print0  | xargs -0 sha1sum

Você precisa usar "-print0" e "-0", caso haja espaços nos nomes dos arquivos.

No entanto, isso é muito semelhante ao padrão "find -exec cmd {}".

Consulte uma discussão comparando os dois padrões aqui: https://stackoverflow.com/questions/896808/find-exec-cmd-vs-xargs


Sua resposta retorna apenas o hash dos arquivos. O hash da pasta deve ser obtido usando find . -type f -print0 | xargs -0 sha1sum | awk '{print $1}' | sha1sum.
Alper 3/08

5

ATUALIZAÇÃO: Faz alguns anos que não postei essa resposta e, enquanto isso, reescrevi e aprimorei o script que apresentei aqui várias vezes. Decidi repassar o novo script como uma resposta totalmente nova. Eu recomendo sobre este.

INTRODUÇÃO

Observei que a ordem na qual o comando find gera os elementos encontrados em um diretório varia em diretórios idênticos em diferentes partições. Se você estiver comparando os hashes do mesmo diretório, não precisará se preocupar com isso, mas se estiver obtendo os hashes para garantir que nenhum arquivo tenha sido perdido ou corrompido durante uma cópia, será necessário incluir uma linha adicional para classificando o conteúdo do diretório e seus elementos. Por exemplo, a resposta de Matthew Bohnsack é bastante elegante:

find ./path/to/directory/ -type f -print0  | xargs -0 sha1sum

Mas se você o estiver usando para comparar um diretório copiado com o original, você enviaria a saída para um arquivo txt que você compararia com a lista de saída do outro diretório usando o Kompare ou o WinMerge ou simplesmente obtendo os hashes de cada lis . O fato é que, como a ordem na qual a ferramenta de localização produzirá o conteúdo pode variar de um diretório para outro, o Kompare sinalizará muitas diferenças porque os hashes não foram calculados na mesma ordem. Não é grande coisa para pequenos diretórios, mas é bastante irritante se você estiver lidando com 30000 arquivos. Portanto, você deve executar as etapas extras de classificação da saída para facilitar a comparação das listas de hash entre os dois diretórios.

find ./path/to/directory/ -type f -print0  | xargs -0 sha1sum > sha1sum_list_unsorted.txt
sort sha1sum_list_unsorted.txt > sha1sum_list_sorted.txt

Isso classificaria a saída para que os arquivos com o mesmo hash fiquem nas mesmas linhas ao executar o programa diferencial (desde que nenhum arquivo esteja faltando no novo diretório).

E NO SCRIPT ...

Aqui está um script que eu escrevi. Ele faz o mesmo que a resposta find / xarg, mas classifica os arquivos antes de obter o sha1sum (mantendo-os no mesmo diretório). A primeira linha do script localiza todos os arquivos no diretório recursivamente. O próximo classifica os resultados em ordem alfabética. Os dois a seguir pegam o conteúdo classificado e anexam um sha1sum e aspas aos arquivos na lista classificada, criando um grande script de shell que calcula o hash de cada arquivo, um de cada vez e o envia para content_sha1sum.txt.

#!/bin/bash
find . -type f > content.txt
sort content.txt > content_sorted.txt
awk '{print "sha1sum \""$0}' content_sorted.txt > temp.txt
awk '{print $0"\""}' temp.txt > get_sha1.sh
chmod +x get_sha1.sh
./get_sha1.sh > content_sha1sum.txt
rm content.txt
rm content_sorted.txt
rm temp.txt
rm get_sha1.sh
xdg-open content_sha1sum.txt

Espero que isto ajude.


Quando o comprimento total de todos os nomes de arquivos se encaixa na linha de comando, passar por sort -z( --zero-terminated) é mais fácil do que mexer com vários arquivos.
Anton Samsonov

@AntonSamsonov Este é um script muito antigo, eu estava apenas aprendendo scripts na época. Desde então, reescrevi várias vezes. No que diz respeito ao seu comentário, o que a terminação zero faz ao classificar: eu li a página de manual da classificação. Eles dizem que a terminação zero adere um byte zero no final da linha, em vez de uma nova linha. O que isso faz?
precisa saber é o seguinte

Eu publiquei uma atualização para este script como uma resposta separada aqui: superuser.com/questions/458326/...
thebunnyrules

4

INTRODUÇÃO

Alguns anos atrás, escrevi e apresentei (neste tópico) um script que pode verificar as assinaturas de hash de todos os arquivos individuais na estrutura de diretórios atual e produzi-lo como uma lista em um arquivo de texto.

Desde então, refinei essa fórmula várias vezes. Decidi postar novamente meu script novo e aprimorado aqui como uma resposta separada. Ele foi escrito para sha256, mas qualquer um que ainda queira usar o sha1 pode fazer uma pesquisa simples e substituir no gedit para trocar o sha256 pelo sha1. Pessoalmente, não uso o sha1 há alguns anos e não o recomendaria, pois ficou antiquado e o Google demonstrou como pode ser comprometido .

Aqui está o que meu novo script faz:

  1. Você pode simplesmente usar o script indo para o diretório que deseja fazer o hash e inserindo:

    sha256rec

    Como alternativa, você pode chamar esse script de outro diretório fazendo:

    sha256rec "/path/to/target/directory/you/want/hash"
  2. O script detectará se você possui privilégios de gravação no diretório atual. Se você fizer isso, os resultados serão salvos no diretório atual. Se você não tiver privilégios de gravação ou se o diretório atual estiver em um sistema somente leitura (como um cdrom), os resultados serão salvos no diretório inicial do usuário atual.

  3. O script detectará se alguns dos subdiretórios não estão acessíveis nos privilégios atuais do usuário. Se tudo estiver legível, nenhuma elevação de privilégio ocorrerá, se não estiver, os privilégios do usuário serão elevados à raiz.

  4. Localizar é usado para encontrar todos os arquivos na estrutura atual do diretório (incluindo todos os subdiretórios). A classificação é usada para garantir que os resultados sejam gerados em ordem alfabética. A lista resultante passa por sha256sum e é gerada em um arquivo de texto.

  5. Desde que escrevi o script antigo, adotei uma filosofia de design de que os arquivos temporários são ruins e devem ser evitados sempre que possível, pois deixam os usuários abertos para bisbilhotar e adulterar por terceiros maliciosos. Portanto, todos os dados desse novo script são manipulados como variáveis ​​até o último minuto em que os resultados são gerados como um arquivo de texto.

  6. O arquivo resultante em si é hash e o caminho / hash é gerado no terminal. Gosto de tirar fotos desses hashes com uma câmera off-line da velha escola para garantir que o arquivo de resultados não seja violado quando me refiro a ele posteriormente.

  7. Arquivos de resultados antigos são ignorados no registro. Facilita a comparação dos resultados.

Aqui está um exemplo da saída do terminal ao executar meu script:

kernelcrunch@ubuntu:/usr/src/linux-headers-4.13.0-16-generic$ sha256rec
======================================================================= 
sha256rec:         
=======================================================================        
Current Folder : /usr/src/linux-headers-4.13.0-16-generic   
Target Folder  : /usr/src/linux-headers-4.13.0-16-generic
Output File    : /home/kernelcrunch/000_sha256sum_recurs_linux-headers-4.13.0-16-generic_d_22-04-2018_t_02.17.txt


Seems you're currently in either a Read-Only system or a root owned directory as a regular user. You can find the hash results in your home folder.
f3ddb06212622c375c6bcc11bd629ce38f6c48b7474054ca6f569ded4b4af9d8  /home/kernelcrunch/000_sha256sum_recurs_linux-headers-4.13.0-16-generic_d_22-04-2018_t_02.17.txt
Operation Length: 10 Seconds.
=======================================================================
kernelcrunch@ubuntu:/usr/src/linux-headers-4.13.0-16-generic$ 

Aqui está um trecho da saída que pode ser encontrada em 000_sha256sum_recurs_linux-headers-4.13.0-16-generic_d_22-04-2018_t_02.17.txt:

79c3f378a42bd225642220cc1e4801deb35c046475bb069a96870ad773082805  ./.9491.d
2e336c69cde866c6f01a3495048d0ebc2871dd9c4cb5d647be029e0205d15ce6  ./.config
174f23ff7a7fba897bfb7cf17e9a501bcecacf7ef0c0d5cf030414c1e257d4e3  ./.config.old
389d83f546b250304a9a01bb3072ff79f9d9e380c8a2106cadbf714a872afe33  ./.missing-syscalls.d
035dc77da819101cb9889b4e515023dddd2c953f00d2653b87c6196a6560903e  ./Module.symvers
b28054d7995233e6d003ceb9ed119a0b3354f5ccf77b8d687fc0353ae3c5bfb8  ./arch/x86/include/generated/asm/.syscalls_32.h.cmd
01cf821170e3e6e592e36a96e8628377151c762ac2ee3210c96004bfaef22f5f  ./arch/x86/include/generated/asm/.syscalls_64.h.cmd
111efa83187c58a74a9b0170fd496b497b0682d109a7c240c17e2ffcc734f4f4  ./arch/x86/include/generated/asm/.unistd_32_ia32.h.cmd
fcba4e8abf9e95472c31708555db844ac43c87260fb0ba706b6f519404bf9aba  ./arch/x86/include/generated/asm/.unistd_64_x32.h.cmd
3264438a54cbf7e62b05d38a93c5df8fe4202ac782a5d83ed202cba9eee71139  ./arch/x86/include/generated/asm/.xen-hypercalls.h.cmd
4bd7a45837da7de379b87242efe562ce06bf9d8ab8f636c205bb5ef384c8f759  ./arch/x86/include/generated/asm/clkdev.h
0d96461abd23bbf2da522822948455413a345f9ef8ac7a7f81c6126584b3c964  ./arch/x86/include/generated/asm/dma-contiguous.h
b1a54c24a12ce2c0f283661121974436cdb09ae91822497458072f5f97447c5d  ./arch/x86/include/generated/asm/early_ioremap.h
dd864107295503e102ea339e0fd4496204c697bdd5c1b1a35864dfefe504a990  ./arch/x86/include/generated/asm/mcs_spinlock.h
782ce66804d000472b3c601978fa9bd98dcf3b2750d608c684dc52dd1aa0eb7e  ./arch/x86/include/generated/asm/mm-arch-hooks.h
cd9913197f90cd06e55b19be1e02746655b5e52e388f13ec29032294c2f75897  ./arch/x86/include/generated/asm/syscalls_32.h
758ce35908e8cfeec956f57a206d8064a83a49298e47d47b7e9a7d37b5d96d59  ./arch/x86/include/generated/asm/syscalls_64.h
1147ca3a8443d9ccbdf9cd1f4b9b633f0b77f0559b83ec5e4fa594eadb2548be  ./arch/x86/include/generated/asm/unistd_32_ia32.h
ca5223fbf8f03613a6b000e20eb275d9b8081c8059bc540481a303ce722d42f3  ./arch/x86/include/generated/asm/unistd_64_x32.h
31703052c0d2ab8fe14b4e5dfcc45fcbd5feb5016b0a729b6ba92caa52b069e2  ./arch/x86/include/generated/asm/xen-hypercalls.h
c085ff1b6e9d06faa3fc6a55f69f9065c54098d206827deec7fe0a59d316fc99  ./arch/x86/include/generated/uapi/asm/.unistd_32.h.cmd
7929c16d349845cebb9e303e0ff15f67d924cac42940d0f7271584f1346635fc  ./arch/x86/include/generated/uapi/asm/.unistd_64.h.cmd
9aa492c5a75f5547f8d1dc454bef78189b8f262d1c4b00323a577907f138a63e  ./arch/x86/include/generated/uapi/asm/.unistd_x32.h.cmd
f568e151bbbb5d51fd531604a4a5ca9f17004142cd38ce019f0d5c661d32e36b  ./arch/x86/include/generated/uapi/asm/unistd_32.h
c45cf378498aa06b808bb9ccf5c3c4518e26501667f06c907a385671c60f14ae  ./arch/x86/include/generated/uapi/asm/unistd_64.h
a0088d8d86d7fd96798faa32aa427ed87743d3a0db76605b153d5124845161e2  ./arch/x86/include/generated/uapi/asm/unistd_x32.h
e757eb6420dffa6b24b7aa38ca57e6d6f0bfa7d6f3ea23bbc08789c7e31d15fa  ./arch/x86/kernel/.asm-offsets.s.cmd
f9e703e4f148d370d445c2f8c95f4a1b1ccde28c149cff2db5067c949a63d542  ./arch/x86/kernel/asm-offsets.s
7971fb3e0cc3a3564302b9a3e1ad188d2a00b653189968bbc155d42c70ce6fbf  ./arch/x86/purgatory/.entry64.o.cmd
8352d79fe81d2cf694880f428e283d79fd4b498cea5a425644da25a9641be26b  ./arch/x86/purgatory/.kexec-purgatory.c.cmd
37f3edbee777e955ba3b402098cb6c07500cf9dc7e1d44737f772ac222e6eb3e  ./arch/x86/purgatory/.purgatory.o.cmd
bb8b895cbd2611b69e2f46c2565b4c2e63a85afb56cff946a555f2d277ee99b2  ./arch/x86/purgatory/.purgatory.ro.cmd
bcc2365c9d3d027f1469806eb4f77b0f3ede6eb0855ea0fcd28aa65884046a54  ./arch/x86/purgatory/.setup-x86_64.o.cmd
872229f334fdcc8562e31b9f6581008c1571ac91f12889cd0ff413590585155a  ./arch/x86/purgatory/.sha256.o.cmd
6fb0cbef120aadee282f7bc3b5ea2f912980f16712281f8f7b65901005194422  ./arch/x86/purgatory/.stack.o.cmd
cd1b61063ae3cf45ee0c58b2c55039f3eac5f67a5154726d288b4708c4d43deb  ./arch/x86/purgatory/.string.o.cmd
e5826f0216fd590972bbc8162dd175f87f9f7140c8101505d8ca5849c850ec91  ./arch/x86/purgatory/entry64.o

(continua por mais de 7000 linhas como essa, mas você entendeu)

INSTALAÇÃO

  1. Abra um terminal e insira os seguintes comandos:

    cd /usr/bin
    sudo su
    echo '#!/bin/bash'> /usr/bin/sha256rec
    chmod +x /usr/bin/sha256rec
    touch /usr/bin/sha256rec
    nano /usr/bin/sha256rec
  2. No nano, use Shif + Ctrl + v para colar. Ctrl-O e Enter para salvar. O Ctr-X sai. Cole meu script lá:

(cole após o #! / bin / bash)

  #FUNCTIONS OR FUNCTYOU?
  function s_readonly { err=$(date +%s%N); cd "$1"; mkdir $err 2> /tmp/$err; rmdir $err 2>/dev/null; echo $(cat /tmp/$err|grep -i "Read-only file system"|wc -l);shred -n 0 -uz /tmp/$err; }
  function w_denied { echo $(err=$(date +%s%N); cd "$1"; mkdir $err 2> /tmp/$err; rmdir $err 2>/dev/null; cat /tmp/$err|grep -i "Permission denied"|wc -l;shred -n 0 -uz /tmp/$err); }
  function r_denied { echo $(err=$(date +%s%N); cd "$1" >/dev/null 2> /tmp/$err; find . >/dev/null 2>> /tmp/$err; cat /tmp/$err|grep -i "Permission denied"|wc -l;shred -n 0 -uz /tmp/$err); }
  function rando_name { rando=$(echo $(date +%s%N)|sha256sum|awk '{print $1}'); rando=${rando::$(shuf -i 30-77 -n 1)}; echo $rando;}
  function ms0 { ms0=$(($(date +%s%N)/1000000)); }; function mstot { echo $(($(($(date +%s%N)/1000000))-$ms0));}
  function s0 { s0=$(date +%s); }; function stot { echo $(($(date +%s)-$s0));}
  s0

  #CHECK IF A TARGET DIR WAS SPECIFIED (-t= or --target= switch)
  if [ ! -z "$1" ]; then arg1="$1"; arg1_3=${arg1::3}; arg1_9=${arg1::9};fi
  if [ "$arg1_3" = "-t=" -o "$arg1_9" = "--target=" ]; then 
    switch=$(echo $arg1|awk -F '=' '{print $1}')
    switch_chr=$((${#switch}+1))
    target=${arg1:$switch_chr}
    current=$(pwd)
    cd "$target"
    arg1="" #<- cancels the not path in the find line
  else
    current=$(pwd)
    target=$(pwd) 
  fi

  echo -e  "=======================================================================\
    \nsha256rec: \
          \n=======================================================================\
          \nCurrent Folder : $current \
    \nTarget Folder  : $target"

  #GETS DEFAULT_USER, ASSUME'S YOU'RE USER 1000, IF 1000 DOESN'T EXIST SEARCHES 999, THEN 1001, 1002
  default_user=$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)
  if [ -z "$default_user" ]; then default_user=$(awk -v val=999 -F ":" '$3==val{print $1}' /etc/passwd); fi
  if [ -z "$default_user" ]; then default_user=$(awk -v val=1001 -F ":" '$3==val{print $1}' /etc/passwd); fi
  if [ -z "$default_user" ]; then default_user=$(awk -v val=1002 -F ":" '$3==val{print $1}' /etc/passwd); fi

  if [ "$(users | wc -l)" = "1" ]; then USER=$(users|awk '{print $1}'); else USER=$default_user;fi #not perfect but meh...

  #running rando_name in this very specific spot between USER detection and Permission detection, some interfers somehow with detection functions... 
  #the rando function placed underneath the user detection is somehow turning c=$current from the dir path to whatever rando_name puts out.

  #FIGURE OUT WHERE TO PUT HASH LIST
  hash_file="000_sha256sum_recurs_${target##*/}_d_$(date +%d-%m-20%y)_t_$(date +%H.%M).txt"
  if [ $(s_readonly "$current") -gt 0 -o $(w_denied "$current") -gt 0 ]; then if [ "$(whoami)" != root ]; then dest="/home/$(whoami)";echo -e "Output File    : $dest/$hash_file\n\n";echo "Seems you're currently in either a Read-Only system or a root owned directory as a regular user. You can find the hash results in your home folder."; else dest="/home/$USER";echo -e "Output File    : $dest/$hash_file\n\n";echo "Seems you're currently a Read-Only system. You can find the hash results in $USER's home folder.";fi; else dest="$current";echo -e "Output File    : $dest/$hash_file\n\n";echo "Results will be saved here.";fi



  #CAN REGULAR USER ACCESS TARGET DIR? ARE ALL IT'S SUBDIRS READABLE?
  if [ $(r_denied "$target") -gt 0 ]; then sudo=sudo; echo "Some folder were not read-able as a regular user. User elevation will be required.";fi

  #PERFORM RECURSIVE HASHING
  command=$($sudo find . -type f -not -type l -not -path "$arg1"  -not -path "$2"  -not -path "$3" -not -path "$4"  -not -path "$5"  -not -path "$6" -not -path "$7"  -not -path "$8"  -not -path "$9" |grep -v "\./000_sha"|sort|awk "{print \"$sudo sha256sum \\\"\"\$0}"|awk '{print $0"\""}'|tr '\n' ';')
  eval $command > "$dest/$hash_file"

  sha256sum "$dest/$hash_file"
  echo "Operation Length: $(stot) Seconds."
  echo -e  "======================================================================="



  if [ "$target" != "$current" ]; then cd "$current";fi


  exit
  #||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
  #||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
  #||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
  #||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
  1. Ao sair do nano, certifique-se de sair do status elevado digitando:

    exit

PENSAMENTOS FINAIS

  1. Isso só funcionará se você tiver o bash instalado. Eu usei alguma sintaxe para manipulação de substring que não funciona com sh, dash, ksh ou zsh. Você ainda pode usar qualquer um dos outros shells como seus drivers diários, mas o bash precisa ser instalado.

  2. As listas produzidas podem ser comparadas com diversas ferramentas, como: (no terminal) diff, sdiff (e gráfica) difusa, kdiff, winmerge.

  3. Meu arquivo classifica a saída com base no caminho, para facilitar a leitura por seres humanos. Notei que o comando de classificação funciona de maneira diferente em diferentes distribuições. Por exemplo, em uma distribuição, as letras CAPITAL priorizavam as letras maiúsculas e, na outra, não. Isso afeta a ordem das linhas dos arquivos de saída e pode dificultar a comparação. Isso não deve apresentar problemas se você estiver sempre usando o script na mesma distribuição, mas poderá se as listas de hashes forem geradas em dois ambientes diferentes. Isso é facilmente remediado, classificando os arquivos hash mais um tempo, para que as linhas sejam ordenadas por hash, e não por caminho:

     cat 000_sha256sum_oldhashlist|sort> ./old
     cat 000_sha256sum_newhashlist|sort> ./new
     sha256sum ./old ./new; diff ./old ./new

Uma linha shebang mais robusta seria #!/usr/bin/env bash- ela também encontrará o Bash em outros diretórios, porque o último pode ser instalado em / usr / bin em vez de / bin , por exemplo, enquanto o env tende a estar em / usr / bin o tempo todo tanto quanto eu notei. Também vale a pena notar que, como você precisa do Bash, você pode usar a [[ blah-blah ]]expressão condicional entre parênteses em vez da [ blah-blah ]variante mais genérica entre parênteses.
Anton Samsonov

Obrigado pelas indicações. Acabei de procurar os condicionais. Eles parecem realmente úteis.
thebunnyrules

A preocupação com o comprometimento do SHA1 não é realmente aplicável no caso de comparar arquivos após a cópia para verificar a integridade. As chances de um arquivo ser corrompido em trânsito, mas ainda ter o mesmo SHA1 são praticamente nulas. Se você suspeitar que um invasor pode ter tido tempo suficiente para gerar um arquivo diferente com um SHA1 em colisão, use o SHA256, mas, no caso típico de cópia de arquivos, é um exagero e mais lento que o SHA1 ou MD5 .
Dan Dascalescu 6/01

Seu próprio argumento pode ser usado contra si mesmo. Se você está preocupado com a corrupção normal (não relacionada a ataques), o sha1 em si é um exagero. Você pode obter resultados mais rápidos usando o md5 / crc32. Em qualquer situação (detecção de violação ou corrupção), sha1 não é um bom ajuste. Pessoalmente, uso essas listas de hash para os dois cenários e não percebi nenhum impacto perceptível no desempenho desde a atualização para o sha256, mas também não estou executando um mega servidor. Como eu disse na resposta, você é livre para usar qualquer hash que desejar, substituindo meu comando sha256sum pelo que deseja: sha1sum, md5sum, b2sum, crc32 ...
thebunnyrules

1

Isso parece funcionar para mim:

find . \( -not -name . \) -type f -exec cat {} + | sha1sum

EDIT: isso somará todos os arquivos contidos na árvore de diretórios. Se o nome de um diretório fosse alterado, isso não ocorreria. Talvez algo como:

find . -exec sha1sum {} + 2>&1 | sha1sum

Faria isso. Sobre a mesma resposta que a outra


1

Outro truque pode ser o uso de tar para misturar o conteúdo e os metadados do arquivo:

tar -cf - ./path/to/directory | sha1sum

muito ruim que eu só tenho um voto
166_MMX

11
Isso não funciona. O tar inclui um registro de data e hora para alguns sistemas operacionais (como OSX) e o sha1sum será diferente a cada execução.
srossross

O que @srossross disse. Além disso, se você tiver versões diferentes do tar nos dois hosts, as saídas serão diferentes.
Dan Dascalescu 6/01

1

Solução rápida, robusta e portátil

Ao contrário de algumas das outras soluções envolvidas tar, a solução abaixo funciona em qualquer máquina que possua os utilitários Unix padrão e é mais rápida que todas as outras soluções, paralelizando a soma de verificação:

find . -type f | xargs -d'\n' -P0 -n1 md5sum | sort -k 2 | md5sum

Como ele usa uma classificação no final, não há progresso em tempo real, então deixe o comando executar.

Aqui está o que os argumentos fazem:

  • find . -type f localiza todos os arquivos no diretório atual e seus subdiretórios
  • xargs -d'\n'divide a saída de localização em linhas (se você espera ter arquivos com novas linhas, faça o habitual find -print0 | xargs -0)
  • -P0 n1é executado md5sumem processos paralelos, usando o número máximo de processos suportados pela máquina (multi-core!)
  • sort -k 2classifica pelo segundo campo da md5sumsaída, que é o caminho completo para cada arquivo (o primeiro é o MD5)
  • o final md5sumcalcula uma soma de verificação da lista de somas de verificação de arquivo, para que você obtenha uma soma de verificação de todo o diretório em uma linha, que você pode comparar facilmente visualmente nas janelas do terminal

Antes de dizer que "o MD5 foi comprometido", lembre-se de qual é o seu modelo de ameaça. Você está tentando garantir que os arquivos copiados de outro host ou disco cheguem intactos? Então o MD5 é mais que suficiente, porque as chances de um arquivo ser corrompido em trânsito, mas com o mesmo MD5, são zero. Mas se você tem medo de um invasor ter tempo para substituir um arquivo por outro com uma soma de verificação em colisão, use sha256sum. A desvantagem é que as funções SHA são mais lentas que o MD5 .

Progresso detalhado em tempo real

Por fim, se você deseja ver o progresso em tempo real, modifique o pipeline para usar um arquivo temporário para as somas de verificação:

find . -type f | xargs -d\\n -P0 -n1 md5sum | tee /tmp/sums && sort -k 2 /tmp/sums | md5sum

(Observe que mover a sortdireita depois findnão funcionaria, porque xargs -P0paraleliza md5sume os resultados podem chegar fora de ordem.)

Esta versão do comando também permite diferenciar os dois /tmp/sumsarquivos (renomeie o segundo se estiver na mesma máquina) e veja quais arquivos diferem.


0

Em vez de ter UM arquivo enorme contendo todas as informações de hash, eu estava procurando uma maneira de criar um arquivo em cada pasta de uma árvore. Eu me inspirei nos comentários aqui. O meu é um pouco mais complexo do que o postado aqui. Eu uso a rotação de arquivos, mas isso é o menos complexo para novos players. Esta versão substituirá as somas de verificação antigas por novas. Pode ser bom manter de duas a três versões, dependendo da frequência com que você a executa e da necessidade de 'profundidade'.

[user @ host bin] $ cat mkshaindir 
#! / bin / dash
cd $ 1
sha512sum *> .sha512sum

[bin usuário @ host] $ find / var / tmp -type d -print0 | xargs -0 -i mkshaindir {}

Observe que mkshaindir, para meus propósitos, é um componente separado, pois pode ser necessário criar um hash de arquivos em uma nova pasta ou em uma que foi alterada recentemente. Tudo isso pode ser combinado em um script, se necessário.

O resto é deixado como um exercício para o leitor.


0

com base na resposta anterior :

find ./path/to/directory -print0 | LC_ALL=C sort --zero-terminated | tar --create --no-recursion --null --files-from /dev/stdin --file /dev/stdout --verbose --numeric-owner | sha1sum

  • classificação estável
  • proprietário numérico e ID do grupo
  • progresso detalhado
  • nome do arquivo seguro

Isso não funcionou em um diretório copiado contendo apenas um arquivo, e eu suspeito que isso ocorreu porque eu estava executando uma versão um pouco mais antiga do tar (1.28) no host remoto, contra 1.29 no host local. Infelizmente, tar 1,29 não foi portado em hospitaleiro.
Dan Dascalescu 6/01

0

@allquixoticA resposta de não gera os mesmos hashes em máquinas diferentes que não nos ajudarão a verificar e ter hashes consistentes.

A linha a seguir find . -type f \( -exec md5sum "$PWD"/{} \; \)retorna a seguinte saída:

d41d8cd98f00b204e9800998ecf8427e  /home/helloWorld.c
24811012be8faa36c8f487bbaaadeb71  /home/helloMars.c

Portanto, o caminho seria diferente em máquinas diferentes. awk '{print $1}'nos ajudará a obter a primeira coluna, que possui apenas o hash dos arquivos. Posteriormente, precisamos classificar esses hashes, onde a ordem pode ser diferente em máquinas diferentes, o que também pode nos levar a ter hashes diferentes, se houver mais de dois arquivos.


Solução:

Para Mac:

find ./path/to/directory/ -type f \( -exec md5 -q  "$PWD"/{} \; \) | awk '{print $1}' | sort | md5

Para Linux:

find ./path/to/directory/ -type f \( -exec md5sum "$PWD"/{} \; \) | awk '{print $1}' | sort | md5sum | awk '{print $1}'
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.