J'ai besoin de calculer une somme de contrôle md5 récapitulative 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?
Edit: Les solutions proposées sont très gentilles, mais ce n’est pas exactement ce dont j’ai besoin. Je cherche une solution pour obtenir un sommaire unique somme de contrôle qui identifiera de manière unique le répertoire dans son ensemble, y compris le contenu de tous ses sous-répertoires.
find /path/to/dir/ -type f -name "*.py" -exec md5sum {} + | awk '{print $1}' | sort | md5sum
La commande find répertorie tous les fichiers se terminant par .py . Le md5sum est calculé pour chaque fichier .py. awk est utilisé pour enlever les sommes md5 (en ignorant les noms de fichiers, qui peuvent ne pas être uniques) . Les sommes md5 sont triées .
J'ai testé cela en copiant un répertoire de test:
rsync -a ~/pybin/ ~/pybin2/
J'ai renommé certains fichiers dans ~/pybin2.
La commande find...md5sum
renvoie le même résultat pour les deux répertoires.
2bcf49a4d19ef9abd284311108d626f1 -
Créez un fichier archive tar à la volée et dirigez-le vers md5sum
:
tar c dir | md5sum
Cela produit une seule somme md5 qui devrait être unique pour la configuration de vos fichiers et sous-répertoires. Aucun fichier n'est créé sur le disque.
la suggestion de ire_and_curses d'utiliser tar c <dir>
pose quelques problèmes:
rsync -a --delete
: il synchronise pratiquement tout (moins xattrs et acls), mais il synchronise le propriétaire et le groupe en fonction de leur ID, et non de la représentation sous forme de chaîne. Donc, si vous avez synchronisé vers un système différent qui n'a pas nécessairement les mêmes utilisateurs/groupes, vous devez ajouter l'indicateur --numeric-owner
à tar.Tant qu'il n'y a pas de solution pour le premier problème (ou si vous n'êtes pas sûr que cela ne vous concerne pas), je n'utiliserais pas cette approche.
Les solutions basées sur find
proposées ci-dessus ne sont pas non plus valables, car elles n'incluent que des fichiers, pas des répertoires, ce qui pose problème si vous devez garder à l'esprit les répertoires vides.
Enfin, la plupart des solutions suggérées ne trient pas systématiquement, car le classement peut être différent d’un système à l’autre.
Voici la solution que j'ai trouvée:
dir=<mydir>; (find "$dir" -type f -exec md5sum {} +; find "$dir" -type d) | LC_ALL=C sort | md5sum
Notes sur cette solution:
LC_ALL=C
permet de garantir un ordre de tri fiable entre les systèmes-print0
pour find
, mais comme il se passe d'autres choses ici, je ne vois que des solutions qui rendraient la commande plus compliquée qu'elle ne valait la peine.PS: L’un de mes systèmes utilise une find
(nombre limité) busybox qui ne prend pas en charge les drapeaux -exec
et -print0
. Il ajoute également un «/» pour indiquer les répertoires, alors que find ne semble pas le trouver.
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 de fichiers/répertoires avec des nouvelles lignes dans leurs noms, donc ce n'est pas un problème sur ce système.
Si vous ne vous souciez que des fichiers et non 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 l'exigence de filtre * .py mais devrait très bien fonctionner avec find (1).
Une solution qui a fonctionné le mieux pour moi:
find "$path" -type f -print0 | sort -z | xargs -r0 md5sum | md5sum
Raison pour laquelle cela a fonctionné le mieux pour moi:
Problèmes avec d'autres réponses:
Les métadonnées du système de fichiers ne sont pas ignorées pour:
tar c - "$path" | md5sum
Ne gère pas les noms de fichiers contenant des espaces et ne détecte pas si le fichier a été renommé:
find /path -type f | sort -u | xargs cat | md5sum
Somme de contrôle de tous les fichiers, y compris le contenu et leurs noms
grep -ar -e . /your/dir | md5sum | cut -c-32
Comme ci-dessus, mais n'incluant que les fichiers * .py
grep -ar -e . --include="*.py" /your/dir | md5sum | cut -c-32
Vous pouvez également suivre les liens symboliques si vous le souhaitez
grep -aR -e . /your/dir | md5sum | cut -c-32
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)
Si vous voulez une somme md5 couvrant tout le répertoire, je ferais quelque chose comme
cat *.py | md5sum
Recherche GNU
find /path -type f -name "*.py" -exec md5sum "{}" +;
Techniquement, vous devez seulement exécuter ls -lR *.py | md5sum
. À moins que vous ne craigniez que quelqu'un modifie les fichiers et les ramène à leur date d'origine sans jamais changer la taille des fichiers, la sortie de ls
devrait vous dire si le fichier a été modifié. Mon unix-foo est faible, vous aurez donc peut-être besoin de plus de paramètres de ligne de commande pour obtenir l'heure de création et l'heure de modification pour l'impression. ls
vous indiquera également si les autorisations sur les fichiers ont changé (et je suis sûr qu'il existe des commutateurs pour désactiver cette option si vous ne vous en souciez pas).
J'utilise HashCopy pour faire cela. 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 de www.jdxsoftware.org.
Utiliser md5deep
:
md5deep -r FOLDER | awk '{print $1}' | sort | md5sum
J'ai eu le même problème alors je suis venu avec ce script qui liste simplement les sommes md5 des fichiers dans le répertoire et s'il trouve un sous-répertoire, il se lance à nouveau à partir de là, pour que cela se produise, le script doit pouvoir être lu dans le fichier courant. répertoire ou depuis 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 être indépendant des attributs du système de fichiers et des différences de niveau binaire de certaines versions de tar, vous pouvez utiliser cpio:
cpio -i -e theDirname | md5sum
Il y a deux autres 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'ai eu des problèmes avec sort
et le tri des noms de fichiers. Donc, au lieu de cela, j'ai trié par résultat md5sum
. J'avais également 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