Annonce

Réduire
Aucune annonce.

Supprimez les doublons avec Python

Réduire
X
 
  • Filtre
  • Heure
  • Afficher
Tout nettoyer
nouveaux messages

  • Supprimez les doublons avec Python

    Voici un petit script utile permettant de supprimer les fichiers en doublon dans une arborescence de dossiers :
    Code:
    #!/usr/bin/python
    
    import sys
    from os import walk
    import hashlib
    import os
    
    def md5(fname):
        hash_md5 = hashlib.md5()
        with open(fname, "rb") as f:
            for chunk in iter(lambda: f.read(4096), b""):
                hash_md5.update(chunk)
        return hash_md5.hexdigest()
    
    def main(path):
        f = []
        for (dirpath, dirnames, filenames) in walk(path):
            for filename in filenames:
                filepath = dirpath+"/"+filename
                try:
                    md5sum = md5(filepath)
    
                    if md5sum not in f:
                        f.append(md5sum)
                    else:
                        print "Removes "+filepath
                        os.remove(filepath)
                except:
                    print "Impossible to manage "+filepath
    
    if __name__ == "__main__":
        if len(sys.argv) != 2 or not os.path.isdir(sys.argv[1]):
            print "Usage : python "+sys.argv[0]+" path"
        else:
            main(sys.argv[1])
    Il est développé en python 2 est peut être lancé depuis la ligne de commande.
    La détection des doublons via un hash en md5.

  • #2
    Merci Anonyme77, de mieux en mieux, ça fait plaisir de voir que tu progresse en développement

    Commentaire


    • #3
      Merci beaucoup pour tes encouragements je suis aussi heureux de me rendre compte que je m'améliore en Python.
      Je suis en effet analyste développeur de profession mais mon langage de prédilection (et celui que j'utilise le plus souvent) reste le Java.

      Je code aussi dans pas mal d'autres langages (Scala, prolog, SQL, Jquery, PHP, Haskell, ...) mais le python a toujours été un de mes petits kiffs personnel (même si je ne le pratique pas trop).

      Commentaire


      • #4
        Bonjour,

        Il y aurait plusieurs questions à se poser dans cette problématique...
        1. Quel doublon je supprime (ne fais-je pas une erreur de supprimer plutôt l'un que l'autre, surtout dans des fichiers systèmes) ?
        2. Pourquoi utiliser md5 ? Alors qu'un module standard existe en python -> difflib
        3. Dommage que tu ne profites pas des mises à jour python et de sa version 3.5, car le module glob fait le taf récursivement et plus rapidement. Pourquoi pas la version 3.x ?

        Après se sont des détails, mais la 1ère question reste essentielle.

        Commentaire


        • #5
          Pour le premier point je pense que si l'on est obligé de se demander l'élément que l'on garde, cela enlève un grosse partie du côté automatique de la suppression.
          L'idée ici était en fait de supprimer les doublons dans, par exemple, une bibliothèque de musiques (dans laquelle on s'en fout un peu de ce qui est supprimé vu qu'elles sont gérées par des logiciels). Je n'expose juste pas toutes mes hypothèses à chaque script que je poste. Ce serait fort long et j'assume que comme toi les mecs lisent le truc avant de le lancer. Ils connaissent donc les effets de bord.

          Pour ce qui est de difflib, je ne connaissais pas mais n'est-ce pas un peu de la "grosse artillerie" de pouvoir voir quelles sont les différences ?
          Au final tout ce que je veux c'est voir que les fichiers sont égaux ou différents pas en quoi ils le sont. Et pour ça je pensais vraiment que les algos de hashs étaient les plus appropriés.
          Ce sont quand même bien eux qui sont vérifier les fichiers que l'on dl non ?

          Concernant glob, je n'ai que survolé mais je ne vois pas son utilisation ici. Peux tu me dire ?

          Commentaire


          • #6
            glob pour lire tous les fichiers récursivement depuis un répertoire

            Code:
            for path in glob.glob(path + '/', recursive=True):
                print(path)
            Pour difflib, c'est basique, ça coûte rien

            Code:
            def comp(fic1, fic2):
                with open(fic1, 'rb') as f1, open(fic2, 'rb') as f2:
                    res = difflib.SequenceMatcher(None, f1.read(), f2.read())
                    if res.ratio() == 1.0:
                        delete(f1) # ou f2
            Mes codes ne sont pas testés, à prendre avec des pincettes.

            Par contre concernant les critères pour ce code tu peux par exemple utiliser ce code pour rechercher les doublons dans un même répertoire, ce qui limite les risques au cas où c'est autre chose que de la musique.

            À la rigueur je préférerai un programme qui me retrouve les doublons et que par la suite je puisse supprimer, voici un code que je propose avec le module itertools pour ne pas louper de comparaisons.

            Code:
            import glob
            import os.path
            from itertools import combinations
            import sys
            
            pathnames = {}
            
            def getContentFiles(pathname, pattern=''):
                PATTERN = pattern
            
                paths = glob.glob(os.path.join(pathname, PATTERN), recursive=False)
            
                for p in paths:
                    with open(p, 'rb') as f:
                        pathnames[p] = f.read()
            
            pathname, pattern = sys.argv[1:]
            
            getContentFiles(pathname, pattern='*.'+pattern)
            for p1, p2 in combinations(pathnames.keys(), 2):
                if pathnames[p1] == pathnames[p2]:
                    print("{} et {} sont identiques".format(p1, p2))
            Pour exécuter le code, en cherchant par exemple les fichiers python,

            En admettant que le fichier python à exécuter soit test.py

            Code:
            python3 test.py /path/que/je/veux py
            Dernière modification par fred, 10 avril 2017, 16h21.

            Commentaire

            Chargement...
            X