Linux: calculer un seul hachage pour un dossier et un contenu donnés?

Il doit Sûrement y avoir un moyen de le faire facilement!

J'ai essayé les applications de ligne de commande linux sha1sum & md5sum mais elles semblent seulement capables de calculer les hachages de fichiers individuels et de produire une liste de valeurs de hachage, une pour chaque fichier.

J'ai besoin de générer un seul hachage pour l'ensemble du contenu d'un dossier (pas seulement les noms de fichiers).

Je voudrais faire quelque chose comme

sha1sum /folder/of/stuff > singlehashvalue

Edit: pour clarifier, mes fichiers sont à plusieurs niveaux dans l'arborescence des répertoires, ils ne sont pas tous dans le même dossier racine.

50
demandé sur Ben L 2009-02-13 12:51:40

14 réponses

Une façon possible serait:

sha1sum path/to/folder/* | sha1sum

S'il y a toute une arborescence de répertoires, il vaut probablement mieux utiliser find et xargs. Une commande possible serait

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

Edit: Bon point, c'est probablement une bonne chose pour trier la liste des fichiers, donc:

find path/to/folder -type f -print0 | sort -z | xargs -0 sha1sum | sha1sum

Et, enfin, si vous devez également tenir compte des autorisations et des répertoires vides:

(find path/to/folder -type f -print0  | sort -z | xargs -0 sha1sum;
 find path/to/folder \( -type f -o -type d \) -print0 | sort -z | \
   xargs -0 stat -c '%n %a') \
| sha1sum

Les arguments de {[4] } lui feront imprimer le nom du fichier, suivi de ses autorisations octales. Le deux trouvailles s'exécuteront l'une après l'autre, provoquant le double de la quantité d'E / S du disque, la première trouvant tous les noms de fichiers et la somme de contrôle du contenu, la seconde trouvant tous les noms de fichiers et de répertoires, le nom et le mode d'impression. La liste des "noms de fichiers et sommes de contrôle", suivie de "noms et répertoires, avec des autorisations" sera alors checksumed, pour une somme de contrôle plus petite.

65
répondu Vatine 2016-01-19 09:18:47
  • Validez le répertoire dans git, utilisez le hachage de validation. Voir metastore pour un moyen de contrôler également les autorisations.

  • Utilisez un outil de détection d'intrusion de système de fichiers comme aide .

  • Hachez une boule de goudron du répertoire:

    tar cvf - /path/to/folder | sha1sum

  • Code quelque chose vous-même, comme oneliner de vatine :

    find /path/to/folder -type f -print0 | sort -z | xargs -0 sha1sum | sha1sum

14
répondu David Schmitt 2018-06-13 19:19:11

Vous pouvez faire tar -c /path/to/folder | sha1sum

6
répondu S.Lott 2018-06-15 16:46:55

Si vous voulez juste vérifier si quelque chose dans le dossier a changé, je recommanderais celui-ci:

ls -alR --full-time /folder/of/stuff | sha1sum

Il vous donnera juste un hachage de la sortie ls, qui contient des dossiers, des sous-dossiers, leurs fichiers, leur horodatage, leur taille et leurs autorisations. À peu près tout ce dont vous auriez besoin pour déterminer si quelque chose a changé.

Veuillez noter que cette commande ne générera pas de hachage pour chaque fichier, mais c'est pourquoi elle devrait être plus rapide que l'utilisation de find.

4
répondu Shumoapp 2016-12-08 00:09:08

Si vous voulez juste hacher le contenu des fichiers, en ignorant les noms de fichiers, vous pouvez utiliser

cat $FILES | md5sum

Assurez-vous que vous avez les fichiers dans le même ordre lors du calcul du hachage:

cat $(echo $FILES | sort) | md5sum

Mais vous ne pouvez pas avoir de répertoires dans votre liste de fichiers.

3
répondu 2009-02-13 09:54:41

Il y a un script python pour cela:

Http://code.activestate.com/recipes/576973-getting-the-sha-1-or-md5-hash-of-a-directory/

Si vous modifiez les noms d'un fichier sans modifier leur ordre alphabétique, le script de hachage ne le détectera pas. Mais, si vous modifiez l'ordre des fichiers ou le contenu d'un fichier, l'exécution du script vous donnera un hachage différent qu'avant.

2
répondu Kingdon 2011-01-25 17:12:41

Je dirigerais les résultats pour les fichiers individuels via sort (pour empêcher une simple réorganisation des fichiers pour changer le hachage) en md5sum ou sha1sum, selon votre choix.

1
répondu Rafał Dowgird 2009-02-13 09:58:39

Un Autre outil pour y parvenir:

Http://md5deep.sourceforge.net/

Tel quel sonne: comme md5sum mais aussi récursif, plus d'autres fonctionnalités.

1
répondu Jack 2015-07-29 13:35:42

J'ai écrit un script Groovy pour faire ceci:

import java.security.MessageDigest

public static String generateDigest(File file, String digest, int paddedLength){
    MessageDigest md = MessageDigest.getInstance(digest)
    md.reset()
    def files = []
    def directories = []

    if(file.isDirectory()){
        file.eachFileRecurse(){sf ->
            if(sf.isFile()){
                files.add(sf)
            }
            else{
                directories.add(file.toURI().relativize(sf.toURI()).toString())
            }
        }
    }
    else if(file.isFile()){
        files.add(file)
    }

    files.sort({a, b -> return a.getAbsolutePath() <=> b.getAbsolutePath()})
    directories.sort()

    files.each(){f ->
        println file.toURI().relativize(f.toURI()).toString()
        f.withInputStream(){is ->
            byte[] buffer = new byte[8192]
            int read = 0
            while((read = is.read(buffer)) > 0){
                md.update(buffer, 0, read)
            }
        }
    }

    directories.each(){d ->
        println d
        md.update(d.getBytes())
    }

    byte[] digestBytes = md.digest()
    BigInteger bigInt = new BigInteger(1, digestBytes)
    return bigInt.toString(16).padLeft(paddedLength, '0')
}

println "\n${generateDigest(new File(args[0]), 'SHA-256', 64)}"

Vous pouvez personnaliser l'utilisation pour éviter d'imprimer chaque fichier, modifier le résumé des messages, supprimer le hachage de répertoire, etc. Je l'ai testé contre les données de test du NIST et cela fonctionne comme prévu. http://www.nsrl.nist.gov/testdata/

gary-macbook:Scripts garypaduana$ groovy dirHash.groovy /Users/garypaduana/.config
.DS_Store
configstore/bower-github.yml
configstore/insight-bower.json
configstore/update-notifier-bower.json
filezilla/filezilla.xml
filezilla/layout.xml
filezilla/lockfile
filezilla/queue.sqlite3
filezilla/recentservers.xml
filezilla/sitemanager.xml
gtk-2.0/gtkfilechooser.ini
a/
configstore/
filezilla/
gtk-2.0/
lftp/
menus/
menus/applications-merged/

79de5e583734ca40ff651a3d9a54d106b52e94f1f8c2cd7133ca3bbddc0c6758
1
répondu haventchecked 2016-03-29 04:59:56

Essayer de le faire en deux étapes:

  1. créez un fichier avec des hachages pour tous les fichiers d'un dossier
  2. hachez ce fichier

Comme ça:

# for FILE in `find /folder/of/stuff -type f | sort`; do sha1sum $FILE >> hashes; done
# sha1sum hashes

Ou tout faire en même temps:

# cat `find /folder/of/stuff -type f | sort` | sha1sum
0
répondu Joao da Silva 2009-02-13 09:57:08

Vous pouvez sha1sum pour générer la liste des valeurs de hachage, puis sha1sum cette liste à nouveau, cela dépend exactement de ce que vous voulez accomplir.

0
répondu Ronny Vindenes 2009-02-13 09:57:21

Une approche robuste et propre

  • tout d'Abord, ne pas monopoliser la mémoire disponible! Hachez un fichier en morceaux plutôt que d'alimenter le fichier entier.
  • différentes approches pour différents besoins / objectifs (tous les ci-dessous ou choisir ce qui s'applique):
    • Hash uniquement le nom d'entrée de toutes les entrées de l'arborescence des répertoires
    • hachez le contenu du fichier de toutes les entrées (en laissant le meta like, le numéro d'inode, ctime, atime, mtime, size,etc., vous obtenez le idée)
    • pour un lien symbolique, son contenu est le nom référent. Hachez-le ou choisissez de sauter
    • suivre ou ne pas suivre (nom résolu) le lien symbolique tout en hachant le contenu de l'entrée
    • Si c'est un répertoire, son contenu ne sont que des entrées de répertoire. En traversant récursivement, ils seront hachés éventuellement, mais les noms d'entrée de répertoire de ce niveau devraient-ils être hachés pour marquer ce répertoire? Utile dans les cas d'utilisation où le hachage est nécessaire pour identifier un changement rapide sans avoir à traverser profondément pour hacher le contenu. Un exemple serait les changements de nom d'un fichier mais le reste du contenu reste le même et ce sont tous des fichiers assez volumineux
    • gérez bien les fichiers volumineux (encore une fois, attention à la RAM)
    • gère les arborescences de répertoires très profondes (attention aux descripteurs de fichiers ouverts)
    • Gérer les noms de fichiers non standard
    • Comment procéder avec les fichiers qui sont prises, pipes/Fifo, les périphériques de bloc, char appareils? Doit les hacher aussi?
    • Ne pas mettre à jour l'accès temps de toute entrée en traversant parce que ce sera un effet secondaire et contre-productif (intuitif? pour certains cas d'utilisation.

C'est ce que j'ai sur la tête, quiconque a passé du temps à travailler sur cela aurait pratiquement attrapé d'autres pièges et des cas de coin.

Voici un outil, très léger sur la mémoire, qui répond à la plupart des cas, peut être un peu rugueux sur les bords, mais a été très utile.

Un exemple d'utilisation et sortie de dtreetrawl.

Usage:
  dtreetrawl [OPTION...] "/trawl/me" [path2,...]

Help Options:
  -h, --help                Show help options

Application Options:
  -t, --terse               Produce a terse output; parsable.
  -j, --json                Output as JSON
  -d, --delim=:             Character or string delimiter/separator for terse output(default ':')
  -l, --max-level=N         Do not traverse tree beyond N level(s)
  --hash                    Enable hashing(default is MD5).
  -c, --checksum=md5        Valid hashing algorithms: md5, sha1, sha256, sha512.
  -R, --only-root-hash      Output only the root hash. Blank line if --hash is not set
  -N, --no-name-hash        Exclude path name while calculating the root checksum
  -F, --no-content-hash     Do not hash the contents of the file
  -s, --hash-symlink        Include symbolic links' referent name while calculating the root checksum
  -e, --hash-dirent         Include hash of directory entries while calculating root checksum

Un extrait de l'homme amicale sortie:

...
... //clipped
...
/home/lab/linux-4.14-rc8/CREDITS
        Base name                    : CREDITS
        Level                        : 1
        Type                         : regular file
        Referent name                :
        File size                    : 98443 bytes
        I-node number                : 290850
        No. directory entries        : 0
        Permission (octal)           : 0644
        Link count                   : 1
        Ownership                    : UID=0, GID=0
        Preferred I/O block size     : 4096 bytes
        Blocks allocated             : 200
        Last status change           : Tue, 21 Nov 17 21:28:18 +0530
        Last file access             : Thu, 28 Dec 17 00:53:27 +0530
        Last file modification       : Tue, 21 Nov 17 21:28:18 +0530
        Hash                         : 9f0312d130016d103aa5fc9d16a2437e

Stats for /home/lab/linux-4.14-rc8:
        Elapsed time     : 1.305767 s
        Start time       : Sun, 07 Jan 18 03:42:39 +0530
        Root hash        : 434e93111ad6f9335bb4954bc8f4eca4
        Hash type        : md5
        Depth            : 8
        Total,
                size           : 66850916 bytes
                entries        : 12484
                directories    : 763
                regular files  : 11715
                symlinks       : 6
                block devices  : 0
                char devices   : 0
                sockets        : 0
                FIFOs/pipes    : 0
0
répondu six-k 2018-01-10 17:55:05

J'ai dû vérifier dans un répertoire entier pour les changements de fichiers.

, Mais avec l'exclusion, l'horodatage, répertoire de la propriété.

Le but est d'obtenir une somme identique n'importe où, si les fichiers sont identiques.

Y compris hébergé dans d'autres machines, indépendamment de tout sauf les fichiers, ou un changement en eux.

md5sum * | md5sum | cut -d' ' -f1

Il génère une liste de hachage par fichier, puis concatène ces hachages en un seul.

C'est beaucoup plus rapide que la méthode tar.

Pour un plus fort confidentialité dans nos tables de hachage, nous pouvons utiliser sha512sum sur la même recette.

sha512sum * | sha512sum | cut -d' ' -f1

Les hachages sont également identiques n'importe où en utilisant sha512sum mais il n'y a aucun moyen connu de l'Inverser.

0
répondu Cryptopat 2018-01-28 16:14:11

Voici une variante simple et courte en Python 3 qui fonctionne bien pour les fichiers de petite taille (par exemple une arborescence source ou quelque chose, où chaque fichier peut facilement s'intégrer dans la RAM), en ignorant les répertoires vides, en fonction des idées des autres solutions:

import os, hashlib

def hash_for_directory(path, hashfunc=hashlib.sha1):                                                                                            
    filenames = sorted(os.path.join(dp, fn) for dp, _, fns in os.walk(path) for fn in fns)         
    index = '\n'.join('{}={}'.format(os.path.relpath(fn, path), hashfunc(open(fn, 'rb').read()).hexdigest()) for fn in filenames)               
    return hashfunc(index.encode('utf-8')).hexdigest()                          

Cela fonctionne comme ceci:

  1. trouve tous les fichiers dans le répertoire récursivement et les trie par nom
  2. calculez le hachage (par défaut: SHA-1) de chaque fichier (lit le fichier entier en mémoire)
  3. créer un texte index avec "filename=hash" lignes
  4. encodez cet index dans une chaîne d'octets UTF-8 et hachez-le

Vous pouvez passer une fonction de hachage différente comme deuxième paramètre si SHA-1 n'est pas votre tasse de thé.

0
répondu Thomas Perl 2018-03-08 11:17:38