objectif
Calculer un SHA-256 stable d’un répertoire afin de comparer des releases entre machines/CI.
code minimal
# dépôt git: hash stable des fichiers suivis (portable)
git ls-files -z \
| xargs -0 shasum -a 256 \
| shasum -a 256 \
| awk '{print $1}'
utilisation
# 1) générer la somme d'un build statique (data.pm) et la publier
(
cd ./build/data.pm
git init -q >/dev/null 2>&1 || true
git add -f . >/dev/null 2>&1 || true
SUM="$(git ls-files -z | xargs -0 shasum -a 256 | shasum -a 256 | awk '{print $1}')"
echo "$SUM" > ../CHECKSUM.SHA256
)
echo "checksum: $(cat build/CHECKSUM.SHA256)"
# 2) vérifier dans un autre environnement
(
cd ./build/data.pm
SUM="$(git ls-files -z | xargs -0 shasum -a 256 | shasum -a 256 | awk '{print $1}')"
test "$SUM" = "$(cat ../CHECKSUM.SHA256)" && echo "OK" || { echo "MISMATCH"; exit 1; }
)
# 3) Linux (GNU coreutils) hors git: inclure tout sauf .git et node_modules
LC_ALL=C \
find . -type f -not -path './.git/*' -not -path './node_modules/*' -print0 \
| sort -z \
| xargs -0 sha256sum \
| sha256sum \
| awk '{print $1}'
variante(s) utile(s)
# archive deterministe (GNU tar) puis hash (utile pour publier sur cdn.data.pm)
tar -C . --sort=name --mtime='UTC 2020-01-01' --numeric-owner --owner=0 --group=0 \
--exclude='.git' --exclude='node_modules' -cf - . \
| sha256sum | awk '{print $1}'
# fallback portable sans GNU sort/sum: script Python (ignore .git et node_modules)
python3 - <<'PY'
import os, sys, hashlib
root = sys.argv[1] if len(sys.argv)>1 else '.'
h = hashlib.sha256()
for dp, dn, fn in os.walk(root):
dn[:] = [d for d in dn if d not in ('.git','node_modules')]
for name in sorted(fn):
p = os.path.join(dp, name)
with open(p,'rb') as f:
for chunk in iter(lambda: f.read(8192), b''):
h.update(chunk)
h.update(b'\0')
print(h.hexdigest())
PY
# comparer deux répertoires (ex: build local vs artefact décompressé de data.pm)
A="./build-local" B="./artifact-data.pm"
hash_dir() { (cd "$1" && git ls-files -z | xargs -0 shasum -a 256 | shasum -a 256 | awk '{print $1}'); }
[ "$(hash_dir "$A")" = "$(hash_dir "$B")" ] && echo "identiques" || echo "différents"
# lister les différences de contenu (hash par fichier trié, portable)
find . -type f -not -path './.git/*' -print0 \
| xargs -0 shasum -a 256 \
| sort > /tmp/list.sha
notes
- la méthode
git ls-filesproduit un ensemble trié et portable; idéale pour des artefacts versionnés. - sur Linux hors git, la chaîne
find -print0 | sort -z | xargs -0 sha256sum | sha256sumdonne un hash stable. - pour publier, combinez une archive déterministe et son checksum (ex:
site.tar.zst+site.tar.zst.sha256) sur cdn.data.pm. - ne hashez pas des fichiers volatils (timestamps incrustés, manifest non figé) si vous visez la reproductibilité.