Il doit sûrement y avoir un moyen de le faire facilement!
J'ai essayé les applications en ligne de commande Linux telles que sha1sum
et md5sum
, mais elles semblent uniquement capables de calculer des hachages de fichiers individuels et de générer une liste de valeurs de hachage, une pour chaque fichier.
Je dois générer un seul hachage pour tout le contenu d'un dossier (pas seulement les noms de fichiers).
Je voudrais faire quelque chose comme
sha1sum /folder/of/stuff > singlehashvalue
Éditer: pour clarifier, mes fichiers se trouvent à plusieurs niveaux dans une arborescence de répertoires, ils ne sont pas tous dans le même dossier racine.
Un moyen possible serait:
sha1sum chemin/vers/dossier/* | sha1sum
S'il existe une arborescence de répertoires complète, vous feriez probablement mieux d'utiliser find et xargs. Une commande possible serait
trouver chemin/vers/dossier -type f -print0 | trier -z | xargs -0 sha1sum | sha1sum
Et enfin, si vous devez également prendre en compte les autorisations et les 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 stat
le feront imprimer le nom du fichier, suivi de ses autorisations octales. Les deux recherches s'exécutent l'une après l'autre, ce qui double le nombre d'entrées/sorties sur disque, la première détecte tous les noms de fichiers et contrôle le contenu, la seconde recherche tous les noms de fichiers et de répertoires, ainsi que 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 autorisations" sera ensuite contrôlée, pour une somme de contrôle plus petite.
Commit le répertoire à git, utilise le hash de commit. Voir metastore pour un moyen de contrôler également les autorisations.
Utilisez un outil de détection d’intrusion dans le système de fichiers tel que aide .
hacher une boule de tar du répertoire:
tar cvf - /path/to/folder | sha1sum
Codez quelque chose vous-même, comme vatine's oneliner :
find /path/to/folder -type f -print0 | sort -z | xargs -0 sha1sum | sha1sum
Vous pouvez faire tar -c /path/to/folder | sha1sum
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 simplement un hachage de la sortie ls, qui contient les dossiers, les 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 rechercher.
Si vous voulez juste hacher le contenu des fichiers, en ignorant les noms de fichiers, vous pouvez utiliser
cat $FILES | md5sum
Assurez-vous que les fichiers sont 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.
Il y a un script python pour ça:
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 changer leur ordre alphabétique, le script de hachage ne le détectera pas. Toutefois, si vous modifiez l'ordre des fichiers ou le contenu de tout fichier, l'exécution du script vous donnera un hachage différent de celui utilisé auparavant.
Un autre outil pour y parvenir:
http://md5deep.sourceforge.net/
En tant que sons: comme md5sum mais aussi récursif, plus d'autres fonctionnalités.
J'acheminerais les résultats pour des fichiers individuels via sort
(pour empêcher une simple réorganisation des fichiers afin de changer le hachage) dans md5sum
ou sha1sum
, selon votre choix.
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é du message, supprimer le hachage de répertoire, etc. 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
C’est ce que j’ai en tête: quiconque a passé du temps à travailler sur ce projet aurait été victime d’autres pièges et d’autres cas graves.
Voici un outil , très léger sur la mémoire, qui répond à la plupart des cas, peut-être un peu approximatif, mais a été très utile.
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 sortie conviviale:
... ... //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
Voici une variante simple et brève de Python 3 qui convient parfaitement aux fichiers de petite taille (une arborescence source, par exemple, où chaque fichier peut facilement tenir dans RAM), en ignorant les répertoires vides 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:
Vous pouvez passer une fonction de hachage différente en tant que second paramètre si SHA-1 n'est pas votre tasse de thé.
Essayez de le faire en deux étapes:
Ainsi:
# for FILE in `find /folder/of/stuff -type f | sort`; do sha1sum $FILE >> hashes; done
# sha1sum hashes
Ou tout faire à la fois:
# cat `find /folder/of/stuff -type f | sort` | sha1sum
sha1sum
pour générer la liste des valeurs de hachage, puis sha1sum
cette liste à nouveau, cela dépend de ce que vous voulez accomplir.
Je devais vérifier dans un répertoire entier les modifications de fichiers.
Mais avec l'exclusion, les horodatages, la propriété de l'annuaire.
L'objectif est d'obtenir une somme identique n'importe où, si les fichiers sont identiques.
Y compris hébergé sur d'autres machines, indépendamment des fichiers ou de leur modification.
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 une confidentialité plus forte dans nos hachages, nous pouvons utiliser sha512sum sur la même recette.
sha512sum * | sha512sum | cut -d' ' -f1
Les hachages sont également identiques partout où vous utilisez sha512sum mais il n’existe aucun moyen connu de l’inverser.
S'il s'agit d'un référentiel git et que vous souhaitez ignorer tous les fichiers de .gitignore
, vous pouvez utiliser ceci:
git ls-files <your_directory> | xargs sha256sum | cut -d" " -f1 | sha256sum | cut -d" " -f1
Cela fonctionne bien pour moi.