Dire si 2 fichiers ont le même contenu, sans tenir compte des dates ni des autres propriétés (à part la longueur, bien entendu).
Faire une lecture binaire du contenu des 2 fichiers pour les comparer.
Cette lecture/comparaison est progressive, et permet de s'arrêter au 1er écart trouvé.
Il faut, bien sûr, gérer toutes les erreurs possibles: fichier n'existe pas, ou erreur d'ouverture, de lecture ou de fermeture.
#!/usr/bin/python # -*- coding: utf-8 -*- import os def compfichiers(nfc1, nfc2, lgbuf=32*1024): """Compare les 2 fichiers et renvoie True seulement s'ils ont un contenu identique""" f1 = f2 = None result = False try: if os.path.getsize(nfc1) == os.path.getsize(nfc2): f1 = open(nfc1, "rb") f2 = open(nfc2, "rb") while True: buf1 = f1.read(lgbuf) if len(buf1) == 0: result = True break buf2 = f2.read(lgbuf) if buf1 != buf2: break f1.close() f2.close() except: if f1 != None: f1.close() if f2 != None: f2.close() raise IOError return result
Les 2 arguments nfc1 et nfc2 doivent être des noms de fichiers complets avec leur chemin.
Je n'ai pas essayé, mais a priori, le code devrait être multi-plateforme.
Cette fonction renvoie 3 résultats possibles:
Voilà comment on y fait appel dans ces 3 cas:
if __name__ == "__main__": import time # 1er cas: les 2 fichiers sont identiques nf1 = r"C:\Python25\DLLs\tk84.dll" nf2 = r"C:\Python25\DLLs\tk84_idem.dll" try: t = time.clock() result = compfichiers(nf1, nf2) t = time.clock()-t print u"Résultat:", result, "%.3f s" % t except: t = time.clock()-t print u"Résultat: Erreur", "%.3f s" % t # 2ème cas: les 2 fichiers sont différents nf1 = r"C:\Python25\DLLs\tk84.dll" nf2 = r"C:\Python25\DLLs\unicodedata.pyd" try: t = time.clock() result = compfichiers(nf1, nf2) t = time.clock()-t print u"Résultat:", result, "%.3f s" % t except: t = time.clock()-t print u"Résultat: Erreur", "%.3f s" % t # 3ème cas: le second fichier n'existe pas nf1 = r"C:\Python25\DLLs\tk84.dll" nf2 = r"C:\Python25\DLLs\cefichiernexistepas.$$$" try: t = time.clock() result = compfichiers(nf1, nf2) t = time.clock()-t print u"Résultat:", result, "%.3f s" % t except: t = time.clock()-t print u"Résultat: Erreur", "%.3f s" % t
Ce qui donne bien les résultas attendus (avec la durée en secondes):
Résultat: True 0.004 s Résultat: False 0.000 s Résultat: Erreur 0.000 s
Le résultat est renvoyé très rapidement, le plus lent étant la comparaison entre 2 fichiers identiques (c'est normal: il faut tout lire!). Mais ici, on a obtenu le résultat “True” en 4 millisecondes avec 2 fichiers identiques d'1Mo chacun.
Avec des fichiers beaucoup plus gros, ça se gâte un peu: avec 4.24Go (c'est l'image iso d'un DVD linux), la réponse demande 3 minutes.
Les solutions passant par la comparaison de résultats de hashage ne sont pas plus rapides (il faut tout de même lire les 2 fichiers pour cela!). De plus, l'égalité des empreintes hash des 2 fichiers ne donne pas la garantie absolue que les 2 contenus sont identiques.
Amusez-vous bien!