Pour opendatarchives, j’essaye de limiter le volume de données historisé et archivé. Les dates de mise à jour figurant dans les métadonnées sont souvent modifiées alors que les données n’ont pas changé, j’essaye donc de trouver un moyen simple, rapide, pour détecter par exemple que le contenu d’un CSV n’a pas changé.
Fichiers CSV
Un simple calcul de hash pourrait aller sauf que les plateformes qui génèrent ces fichiers à la volée (OpenDataSoft par exemple) ne fournissent pas forcément les lignes du CSV dans le même ordre.
Le hash est différent alors que les lignes sont identiques mais dans un ordre différent.
Un tri des lignes du fichier, avant calcul du hash contourne le problème:
[ "$(sort fichier1 | md5sum)" = "$(sort fichier2 | md5sum)" ] && echo "identique" || echo "different"
Ceci ne fonctionne pas forcément sur des CSV contenant du texte multiligne… dans ce cas il faut utiliser un vrai tri de fichier CSV, par exemple avec csvsort provenant de csvkit:
[ "$(csvsort fichier1 | md5sum)" = "$(csvsort fichier2 | md5sum)" ] && echo "identique" || echo "different"
Son inconvénient apparaît avec de gros fichiers CSV… il consomme de la RAM et du CPU pour le parsing du CSV.
On peut aussi détecter si un fichier CSV « grossit », c’est à dire que des lignes sont ajoutées mais aucune supprimées, avec un sort + diff + grep + wc par exemple pour retourner le nombre de lignes supprimées:
diff <(sort fichier1) <(sort fichier2) | grep '^<' -c
Fichiers json (et geojson)
Là c’est jq qui permet de trier le json avec l’option -S pour le comparer:
[ "$(jq . -S fichier1 | md5sum)" = "$(jq . -S fichier2 | md5sum)" ] && echo "identique" || echo "different"