Comment puis-je calculer une somme de contrôle md5 d'un répertoire?
Question
Je dois calculer une somme de contrôle md5 sommaire pour tous les fichiers d'un type particulier (*.py
par exemple) placés dans un répertoire et tous les sous-répertoires.
Quelle est la meilleure façon de le faire?
Modifier Les solutions proposées sont très bien, mais ce n'est pas exactement ce que j'ai besoin. Je suis à la recherche d'une solution pour obtenir une somme de contrôle Résumé unique qui identifiera de manière unique le répertoire dans son ensemble -. Y compris le contenu de tous ses sous-répertoires
La solution
find /path/to/dir/ -type f -name "*.py" -exec md5sum {} + | awk '{print $1}' | sort | md5sum
Les listes de commandes de trouver tous les fichiers qui se terminent par .py. Le md5sum est calculé pour chaque fichier .py. awk est utilisé pour enlever les md5sums (abstraction faite des noms de fichiers qui ne peuvent être uniques). Les md5sums sont classés. La md5sum de cette liste triée est alors retourné.
Je l'ai testé en copiant un répertoire de test:
rsync -a ~/pybin/ ~/pybin2/
Je renomme certains fichiers dans ~ / pybin2.
La commande find...md5sum
retourne la même sortie pour les deux répertoires.
2bcf49a4d19ef9abd284311108d626f1 -
Autres conseils
Créez un fichier d'archive tar à la volée et tuyau à md5sum
:
tar c dir | md5sum
Ce produit un seul md5sum qui doit être unique à votre fichier et la configuration sous-répertoire. Aucun sont créés sur le disque.
suggestion de ire_and_curses d'utiliser tar c <dir>
a quelques problèmes:
- tar traite les entrées de répertoire dans l'ordre où ils sont stockés dans le système de fichiers, et il n'y a aucun moyen de changer cet ordre. Cette efficacité peut donner des résultats complètement différents si vous avez le « même » répertoire sur différents endroits, et je sais pas moyen de résoudre ce problème (goudron ne peut pas « trier » les fichiers d'entrée dans un ordre particulier).
- Je me soucie généralement de savoir si le nombre groupId et OWNERID sont les mêmes, pas nécessairement si la représentation de chaîne du groupe / propriétaire sont les mêmes. Ceci est conforme à ce que par exemple
rsync -a --delete
fait: il synchronise pratiquement tout (moins xattrs et ACLs), mais il sera synchronisé propriétaire et le groupe en fonction de leur ID, et non sur la représentation de la chaîne. Donc, si vous avez synchronisé à un autre système qui ne doit pas nécessairement les mêmes utilisateurs / groupes, vous devez ajouter le drapeau--numeric-owner
à goudron - tar comprendra le nom du répertoire que vous se vérifier, juste quelque chose à être au courant.
Tant qu'il n'y a pas de solution pour le premier problème (ou si vous n'êtes pas sûr qu'il ne vous affecte pas), je ne voudrais pas utiliser cette approche.
Les solutions proposées ci-dessus de find
sont également pas bien parce qu'ils ne comprennent que des fichiers, des répertoires non, qui devient un problème si vous le checksumming devrait garder à l'esprit les répertoires vides.
Enfin, les solutions les plus suggérées ne pas trier systématiquement, car la collecte pourrait être différente selon les systèmes.
Ceci est la solution que je suis venu avec:
dir=<mydir>; (find "$dir" -type f -exec md5sum {} +; find "$dir" -type d) | LC_ALL=C sort | md5sum
Notes sur cette solution:
- Le
LC_ALL=C
est d'assurer l'ordre de tri fiable dans les systèmes - Cela ne fait pas de distinction entre un répertoire « nommé \ nwithanewline » et deux répertoires « nom » et « withanewline », mais la chance que semble très improbable survenant. On fixe habituellement ce avec un drapeau de
-print0
pourfind
mais comme il y a d'autres choses qui se passent ici, je ne peux voir des solutions qui rendraient la commande plus compliquée, alors il vaut la peine.
PS: un de mes systèmes utilise un find
busybox limité qui ne supporte pas les drapeaux de -exec
ni -print0
, et aussi ajoute « / » pour désigner les répertoires, alors que findutils trouvent ne semble pas, donc pour cette machine que je dois exécutez:
dir=<mydir>; (find "$dir" -type f | while read f; do md5sum "$f"; done; find "$dir" -type d | sed 's#/$##') | LC_ALL=C sort | md5sum
Heureusement, je n'ai pas les fichiers / répertoires avec des sauts de ligne dans leurs noms, donc ce n'est pas un problème sur ce système.
Si vous ne vous préoccupez pas des fichiers et des répertoires vides, cela fonctionne bien:
find /path -type f | sort -u | xargs cat | md5sum
Par souci d'exhaustivité, il y a md5deep (1) ; ce n'est pas directement applicable en raison de * exigence de filtre .py mais devrait faire bien ensemble avec find (1).
Une solution qui fonctionne le mieux pour moi:
find "$path" -type f -print0 | sort -z | xargs -r0 md5sum | md5sum
Raison pour laquelle il a travaillé le mieux pour moi:
- gère les noms de fichiers contenant des espaces
- Ignore données méta-système de fichiers
- Détecte si le fichier a été renommé
Problèmes avec les autres réponses:
Filesystem méta-données ne sont pas ignorées pour:
tar c - "$path" | md5sum
ne gère pas les noms de fichiers contenant des espaces ne détecte si le fichier a été renommé:
find /path -type f | sort -u | xargs cat | md5sum
Si vous voulez un md5sum couvrant tout le répertoire, je ferais quelque chose comme
cat *.py | md5sum
checksum tous les fichiers, y compris les contenus et leurs noms de fichiers
grep -ar -e . /your/dir | md5sum | cut -c-32
Comme ci-dessus, mais comprenant seulement les fichiers * py
grep -ar -e . --include="*.py" /your/dir | md5sum | cut -c-32
Vous pouvez également suivre les liens symboliques si vous voulez
grep -aR -e . /your/dir | md5sum | cut -c-32
D'autres options que vous pourriez envisager d'utiliser avec 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)
trouver GNU
find /path -type f -name "*.py" -exec md5sum "{}" +;
Techniquement, vous ne devez exécuter ls -lR *.py | md5sum
. À moins que vous êtes inquiet au sujet de quelqu'un modifier les fichiers et les toucher à leurs dates originales et ne jamais changer les tailles des fichiers, la sortie de ls
devrait vous dire si le fichier a changé. Mon unix-foo est faible et vous pourriez avoir besoin des plusieurs paramètres de ligne de commande pour obtenir la création et le temps de modification pour imprimer. ls
vous indiquera également si les autorisations sur les fichiers ont changé (et je suis sûr qu'il ya des interrupteurs pour éteindre ça si vous ne vous inquiétez pas à ce sujet).
J'utilise HashCopy pour ce faire. Il peut générer et vérifier MD5 et SHA sur un seul fichier ou un répertoire. Il peut être téléchargé à partir www.jdxsoftware.org.
Utilisation md5deep
:
md5deep -r FOLDER | awk '{print $1}' | sort | md5sum
J'ai eu le même problème, donc je suis venu avec ce script qui répertorie seulement les md5sums des fichiers dans le répertoire et si elle trouve un sous-répertoire, il court à nouveau à partir de là, pour cela le script doit être en mesure d'exécuter dans le répertoire courant ou d'un sous-répertoire si ledit argument est passé dans $ 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
Si vous voulez vraiment Independance à partir des attributs du système de fichiers et des différences de niveau de bits de certaines versions de goudron, vous pouvez utiliser cpio:
cpio -i -e theDirname | md5sum
Il y a deux solutions:
Créer:
du -csxb /path | md5sum > file
ls -alR -I dev -I run -I sys -I tmp -I proc /path | md5sum > /tmp/file
Vérifier:
du -csxb /path | md5sum -c file
ls -alR -I dev -I run -I sys -I tmp -I proc /path | md5sum -c /tmp/file
md5sum
a bien fonctionné pour moi, mais j'eu des problèmes avec les noms de fichiers sort
et le tri. Ainsi, au lieu que je trié par résultat md5sum
. J'ai aussi besoin d'exclure certains fichiers afin de créer des résultats comparables.
find . -type f -print0 \
| xargs -r0 md5sum \
| grep -v ".env" \
| grep -v "vendor/autoload.php" \
| grep -v "vendor/composer/" \
| sort -d \
| md5sum