sha1sum pour un répertoire de répertoires

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

ce qui précède a été publié comme un moyen de calculer un sha1sum d'un répertoire qui contient des fichiers. Cette commande échoue si le répertoire comprend plus de répertoires. Existe-t-il un moyen de calculer récursivement le sha1sum d'un répertoire de répertoires universellement (sans ajustement personnalisé d'un algorithme au répertoire particulier en question)?

Ocasta Eshu
la source

Réponses:

14

Merci à ce message SO -

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

Attention: ce code n'est pas testé ! Modifiez cette question si elle ne va pas et que vous pouvez la corriger; J'approuverai votre modification.

allquixotic
la source
Désolé; Je n'ai pas pu résister! ;-) La récursivité est amusante. Bien sûr, il existe un moyen. Je vais écrire une bonne réponse maintenant.
allquixotic
3
Cela ne générera pas le même hachage pour les mêmes dossiers exacts sur les différentes machines, car la sortie contient également <hash> et <chemin de fichier>, lequel chemin de fichier est différent sur différentes machines et provoque un hachage différent sur différentes machines. La ligne correcte devrait être comme find . -type f \( -exec sha1sum "$PWD"/{} \; \) | awk '{print $1}' | sort | sha1sum@allquixotic
alper
1
En plus de cela, les hachages de fichiers doivent être classés, ce qui entraînera également des hachages différents si l'ordre de tri est différent sur différentes machines.
alper
40

J'aime généralement le modèle "find | xargs", comme ceci:

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

Vous devez utiliser "-print0" et "-0", au cas où il y aurait des espaces dans les noms de fichiers.

Cependant, ceci est très similaire au modèle "find -exec cmd {}".

Voir une discussion comparant les deux modèles ici: https://stackoverflow.com/questions/896808/find-exec-cmd-vs-xargs

Matthew Bohnsack
la source
Votre réponse renvoie uniquement le hachage des fichiers. Le hachage du dossier doit être obtenu à l'aide de find . -type f -print0 | xargs -0 sha1sum | awk '{print $1}' | sha1sum.
alper
5

MISE À JOUR: Cela fait quelques années que je n'ai pas posté cette réponse et en attendant j'ai réécrit et amélioré le script que j'ai présenté ici plusieurs fois. J'ai décidé de republier le nouveau script comme une toute nouvelle réponse. Je le recommande vivement par rapport à celui-ci.

INTRODUCTION

J'ai observé que l'ordre dans lequel la commande find génère les éléments trouvés dans un répertoire varie au sein de répertoires identiques sur différentes partitions. Si vous comparez les hachages du même répertoire, vous n'avez pas à vous en soucier, mais si vous obtenez les hachages pour vous assurer qu'aucun fichier n'a été manqué ou corrompu lors d'une copie, vous devez inclure une ligne supplémentaire pour trier le contenu du répertoire et ses éléments. Par exemple, la réponse de Matthew Bohnsack est assez élégante:

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

Mais si vous l'utilisez pour comparer un répertoire copié à son original, vous enverriez la sortie dans un fichier txt que vous compareriez à la liste sortie de l'autre répertoire en utilisant Kompare ou WinMerge ou en obtenant simplement les hachages de chaque lis . Le fait est que l'ordre dans lequel l'outil de recherche affichera le contenu peut varier d'un répertoire à l'autre, Kompare signalera de nombreuses différences car les hachages n'ont pas été calculés dans le même ordre. Pas un gros problème pour les petits répertoires mais assez ennuyeux si vous traitez avec 30000 fichiers. Par conséquent, vous devez effectuer les étapes supplémentaires de tri de la sortie pour faciliter la comparaison des listes de hachage entre les deux répertoires.

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

Cela trierait la sortie afin que les fichiers avec le même hachage soient sur les mêmes lignes lors de l'exécution du programme de différenciation (à condition qu'aucun fichier ne manque dans le nouveau répertoire).

ET SUR LE SCRIPT ...

Voici un script que j'ai écrit. Il fait la même chose que la réponse find / xarg, mais il triera les fichiers avant d'obtenir le sha1sum (en les conservant dans le même répertoire). La première ligne du script recherche récursivement tous les fichiers du répertoire. Le suivant trie les résultats par ordre alphabétique. Les deux suivants prennent le contenu trié et ajoutent un sha1sum et des guillemets aux fichiers de la liste triée, créant un gros script shell qui calcule chaque hachage de fichiers, un à la fois et le génère dans 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

J'espère que cela t'aides.

thebunnyrules
la source
Lorsque la longueur totale de tous les noms de fichiers tient dans la ligne de commande, il est plus facile de passer par sort -z( --zero-terminated) que de jouer avec un tas de fichiers.
Anton Samsonov
@AntonSamsonov Ceci est un très vieux script, je venais d'apprendre le script à l'époque. Je l'ai depuis réécrit un tas de fois. En ce qui concerne votre commentaire, que fait la terminaison zéro lors du tri: j'ai lu la page de manuel de tri. Ils disent que la terminaison zéro colle un octet zéro à la fin de la ligne au lieu d'une nouvelle ligne. Qu'est-ce que cela accomplit?
thebunnyrules
J'ai posté une mise à jour de ce script comme réponse distincte ici: superuser.com/questions/458326/…
thebunnyrules
4

INTRODUCTION

Il y a quelques années, j'ai écrit et présenté (dans ce fil même) un script qui peut vérifier les signatures de hachage de tous les fichiers individuels dans la structure de répertoires actuelle et les afficher sous forme de liste dans un fichier texte.

Depuis, j'ai raffiné cette formule plusieurs fois. J'ai décidé de republier mon nouveau script amélioré ici comme réponse distincte. Il est écrit pour sha256 mais toute personne souhaitant toujours utiliser sha1 peut faire une recherche simple et remplacer dans gedit pour échanger sha256 avec sha1. Personnellement, je n'ai pas utilisé sha1 depuis quelques années et je ne le recommanderais pas car il est devenu obsolète et Google a montré comment il pouvait être compromis .

Voici ce que fait mon nouveau script:

  1. Vous pouvez simplement utiliser le script en allant dans le répertoire que vous souhaitez hacher et en entrant:

    sha256rec

    Alternativement, vous pouvez appeler ce script à partir d'un autre répertoire en faisant:

    sha256rec "/path/to/target/directory/you/want/hash"
  2. Le script détectera si vous avez des privilèges d'écriture dans le répertoire actuel. Si vous le faites, les résultats seront enregistrés dans le répertoire actuel. Si vous ne disposez pas de privilèges d'écriture ou si votre répertoire actuel se trouve dans un système en lecture seule (tel qu'un cdrom), les résultats seront enregistrés dans le répertoire de base de l'utilisateur actuel.

  3. Le script détectera si certains des sous-répertoires ne sont pas accessibles avec les privilèges d'utilisateur actuels. Si tous sont lisibles, aucune élévation de privilège n'a lieu, sinon, les privilèges de l'utilisateur sont élevés à la racine.

  4. Find est utilisé pour rechercher tous les fichiers dans la structure dir actuelle (y compris tous les sous-répertoires). Le tri est utilisé pour s'assurer que les résultats sont sortis par ordre alphabétique. La liste résultante subit sha256sum et est sortie dans un fichier texte.

  5. Depuis l'écriture de l'ancien script, j'ai adopté une philosophie de conception selon laquelle les fichiers temporaires sont malveillants et doivent être évités autant que possible car ils laissent les utilisateurs ouverts à l'espionnage et à la falsification par des tiers malveillants. Ainsi, toutes les données de ce nouveau script sont manipulées en tant que variables jusqu'à la toute dernière minute où les résultats sont sortis sous forme de fichier texte.

  6. Le fichier résultant lui-même est haché et le chemin / hachage est sorti dans le terminal. J'aime prendre des photos de ces hachages avec un appareil photo hors ligne de la vieille école pour pouvoir m'assurer que le fichier de résultats n'a pas été falsifié lorsque je m'en réfère à une date ultérieure.

  7. Les anciens fichiers de résultats sont ignorés dans le décompte. Cela facilite la comparaison des résultats.

Voici un exemple de la sortie du terminal lors de l'exécution de mon 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$ 

Voici un extrait de la sortie qui se trouve dans 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

(ça continue pour encore 7000+ lignes comme ça mais vous avez l'idée)

INSTALLATION

  1. Ouvrez un terminal et entrez les commandes suivantes:

    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. Dans nano, utilisez Shif + Ctrl + v pour coller. Ctrl-O et Entrée pour enregistrer. Ctr-X se ferme. Collez mon script là-dedans:

(coller après le #! / 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. Lorsque vous quittez nano, assurez-vous de quitter le statut élevé en entrant:

    exit

DERNIÈRES PENSÉES

  1. Cela ne fonctionnera que si vous avez installé bash. J'ai utilisé un synthax pour la manipulation de sous-chaînes qui ne fonctionne pas avec sh, dash, ksh ou zsh. Vous pouvez toujours utiliser n'importe lequel des autres shells comme pilotes quotidiens, mais bash doit être installé.

  2. Les listes produites peuvent être comparées à une variété d'outils tels que: (dans le terminal) diff, sdiff (et graphique) diffuse, kdiff, winmerge.

  3. Mon fichier trie la sortie en fonction du chemin d'accès, pour le rendre plus facile à lire par les humains. J'ai remarqué que la commande de tri fonctionnait différemment selon les différentes distributions. Par exemple, dans une distribution, les lettres MAJUSCULES ont priorité sur les non-majuscules et dans l'autre non. Cela affecte l'ordre des lignes des fichiers de sortie et pourrait rendre les fichiers difficiles à comparer. Cela ne devrait poser aucun problème si vous utilisez toujours le script dans la même distribution, mais cela peut se produire si des listes de hachages ont été générées dans deux environnements différents. Ceci est facilement résolu en triant les fichiers de hachage une fois supplémentaire afin que les lignes soient ordonnées par hachage plutôt que par chemin:

     cat 000_sha256sum_oldhashlist|sort> ./old
     cat 000_sha256sum_newhashlist|sort> ./new
     sha256sum ./old ./new; diff ./old ./new
thebunnyrules
la source
Une ligne de shebang plus robuste serait #!/usr/bin/env bash- elle trouvera également Bash dans d'autres répertoires, car ce dernier peut être installé dans / usr / bin plutôt que / bin , par exemple, pendant ce temps, env a tendance à être dans / usr / bin à tout moment autant que je l'ai remarqué. Il convient également de noter que, puisque vous avez besoin de Bash, vous pouvez utiliser [[ blah-blah ]]une expression conditionnelle à double crochet au lieu d'une [ blah-blah ]variante plus générique à simple crochet.
Anton Samsonov
Merci pour les pointeurs. Je viens de terminer la recherche des [[conditionnels. Ils ont l'air vraiment utiles.
thebunnyrules
La crainte que SHA1 ne soit compromise n'est pas vraiment applicable dans le cas de la comparaison de fichiers après la copie pour vérifier l'intégrité. Les chances qu'un fichier soit corrompu en transit mais qu'il ait toujours le même SHA1 sont pratiquement nulles. Si vous pensez qu'un attaquant aurait pu avoir suffisamment de temps pour générer un fichier différent avec un SHA1 entrant en collision, utilisez SHA256, mais dans le cas typique de la copie de fichiers, c'est excessif et plus lent que SHA1 ou MD5 .
Dan Dascalescu
Votre propre argument peut être utilisé contre lui-même. Si vous êtes préoccupé par une corruption normale (non liée à une attaque), alors sha1 lui-même est exagéré. Vous pouvez obtenir des résultats plus rapides en utilisant md5 / crc32. Dans les deux situations (détection de sabotage ou corruption), sha1 ne convient pas. Personnellement, j'utilise ces listes de hachage pour les deux scénarios et je n'ai pas remarqué de performances perceptibles depuis que je suis passé à sha256, mais je n'exécute pas non plus un méga serveur. Comme je l'ai dit dans la réponse, vous êtes libre d'utiliser le hachage de votre choix en remplaçant ma commande sha256sum par celle que vous voulez: sha1sum, md5sum, b2sum, crc32 ...
thebunnyrules
1

Cela semble fonctionner pour moi:

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

EDIT: cela ne fera que la somme de tous les fichiers contenus dans l'arborescence des répertoires. Si le nom d'un répertoire était changé, cela ne l'attraperait pas. Peut-être quelque chose comme:

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

Je le ferais. À peu près la même réponse que l'autre

d0c_s4vage
la source
1

Une autre astuce pourrait être d'utiliser tar pour hacher le contenu et les métadonnées du fichier:

tar -cf - ./path/to/directory | sha1sum
kvz
la source
dommage que je n'ai qu'une seule voix
166_MMX
1
Cela ne fonctionne pas. tar inclut un horodatage pour certains systèmes d'exploitation (comme OSX) et le sha1sum sera différent à chaque exécution.
srossross
Ce que @srossross a dit. De plus, si vous avez différentes versions de tar sur les deux hôtes, les sorties seront différentes.
Dan Dascalescu
1

Solution rapide, robuste et portable

Contrairement à certaines des autres solutions impliquant tar, la solution ci-dessous fonctionne sur n'importe quelle machine disposant des utilitaires Unix standard et est plus rapide que toutes les autres solutions en parallélisant la somme de contrôle:

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

Puisqu'il utilise un tri à la fin, il n'y a pas de progression en temps réel, alors laissez la commande s'exécuter.

Voici ce que font les arguments:

  • find . -type f trouve tous les fichiers dans le répertoire courant et ses sous-répertoires
  • xargs -d'\n'divise la sortie de find en lignes (si vous vous attendez à avoir des fichiers contenant des retours à la ligne, faites comme d'habitude find -print0 | xargs -0)
  • -P0 n1s'exécute md5sumdans des processus parallèles, en utilisant le nombre maximum de processus pris en charge par la machine (multicœur!)
  • sort -k 2trie par le deuxième champ de la md5sumsortie, qui est le chemin d'accès complet à chaque fichier (le premier est le MD5)
  • la finale md5sumcalcule une somme de contrôle de la liste des sommes de contrôle de fichier, de sorte que vous obtenez une somme de contrôle de l'ensemble du répertoire sur une seule ligne, que vous pouvez facilement comparer visuellement à travers les fenêtres de terminal

Avant de dire que «MD5 a été compromis», n'oubliez pas quel est votre modèle de menace. Essayez-vous de vous assurer que les fichiers que vous avez copiés à partir d'un autre hôte ou disque sont arrivés intacts? Alors MD5 est plus que suffisant, car les chances qu'un fichier soit corrompu en transit mais ayant le même MD5 sont nulles. Mais si vous avez peur qu'un attaquant ait le temps de remplacer un fichier par un autre avec une somme de contrôle en collision, alors utilisez sha256sum. L'inconvénient est que les fonctions SHA sont plus lentes que MD5 .

Progression détaillée en temps réel

Enfin, si vous souhaitez voir la progression en temps réel, modifiez le pipeline pour utiliser un fichier temporaire pour les sommes de contrôle:

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

(Notez que déplacer la sortdroite après findne fonctionnerait pas, car xargs -P0parallélise md5sumet les résultats peuvent arriver dans le désordre.)

Cette version de la commande vous permet également de différencier les deux /tmp/sumsfichiers (assurez-vous de renommer le second s'il se trouve sur la même machine) et de voir quels fichiers diffèrent.

Dan Dascalescu
la source
0

Plutôt que d'avoir UN énorme fichier contenant toutes les informations hachées, je cherchais un moyen de créer un fichier dans chaque dossier d'une arborescence. Je me suis inspiré des commentaires ici. Le mien est un peu plus complexe que ce qui est affiché ici. J'utilise la rotation des fichiers mais c'est la moins complexe pour les nouveaux joueurs. Cette version fera écraser les anciennes sommes de contrôle par de nouvelles. Il peut être bon de conserver 2 ou 3 versions selon la fréquence à laquelle vous l'exécutez et votre besoin de «profondeur».

[utilisateur @ hôte bin] $ cat mkshaindir 
#! / bin / dash
cd $ 1
sha512sum *> .sha512sum

[bin utilisateur @ hôte] $ find / var / tmp -type d -print0 | xargs -0 -i mkshaindir {}

Notez que mkshaindir, pour mes besoins, est un composant distinct, car il peut être nécessaire de créer un hachage de fichiers dans un nouveau dossier ou d'un fichier récemment modifié. Tout cela peut être combiné en un seul script si nécessaire.

Le reste est laissé comme exercice au lecteur.

Chris
la source
0

basé sur la réponse précédente :

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

  • tri stable
  • propriétaire numérique et identifiant de groupe
  • progrès verbeux
  • nom de fichier sûr
166_MMX
la source
Cela ne fonctionnait pas sur un répertoire copié contenant un seul fichier, et je soupçonne que c'était parce que j'exécutais une version légèrement plus ancienne de tar (1.28) sur l'hôte distant, contre 1.29 sur l'hôte local. Malheureusement, tar 1.29 n'a pas été rétroporté sur Xenial.
Dan Dascalescu
0

@allquixoticLa réponse de ne génère pas les mêmes hachages sur différentes machines, ce qui ne nous aidera pas à vérifier et à avoir des hachages cohérents.

La ligne find . -type f \( -exec md5sum "$PWD"/{} \; \)suivante renvoie la sortie suivante:

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

Par conséquent, le chemin serait différent sur différentes machines. awk '{print $1}'nous aidera à obtenir la première colonne, qui n'a que le hachage des fichiers. Plus tard, nous devons trier ces hachages, où l'ordre peut être différent sur différentes machines, ce qui peut également nous amener à avoir des hachages différents s'il y a plus de deux fichiers.


Solution:

Pour Mac:

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

Pour Linux:

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