]> gitweb.pimeys.fr Git - scripts-20-100.git/blob - mails/rmdups.py
[record.sh] On peut faire des compétitions où les jeunes ont une chance
[scripts-20-100.git] / mails / rmdups.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 """ Pour supprimer des mails présents en double dans un dossier Imap.
5 Supprimme toujours les doublons les plus lourds.
6
7 Des "doublons" sont des mails qui ont le même Message-Id. """
8
9 from __future__ import print_function
10
11 import sys
12 import os
13 import re
14 import collections
15 import argparse
16 import pprint
17
18 def get_files(dir):
19 """Donne les fichiers dans le dossier."""
20 l = [os.path.join(dir, f) for f in os.listdir(dir)]
21 return [f for f in l if os.path.isfile(f)]
22
23 def message_id(file):
24 """Récupère le message-id du mail"""
25 l = re.findall("^Message-I(?:D|d): <(.*)>", open(file, "r").read(), flags=re.MULTILINE)
26 if l:
27 return l[0]
28
29 def finddups(dir, verbose=False):
30 """Trouve les doublons dans ``dir``"""
31 todelete = []
32 l = get_files(dir)
33 d = collections.defaultdict(lambda : [])
34 for f in l:
35 d[message_id(f)].append(f)
36 # On affiche les fichiers pour lesquels on n'a pas réussi à trouver de Message-ID
37 if d[None]:
38 print("Attention : Fichiers sans Message-ID :", file=sys.stderr)
39 for f in d[None]:
40 print(f, file=sys.stderr)
41 # On ne les considère pas comme des doublons
42 del d[None]
43 d = {id : files for (id, files) in d.iteritems() if len(files) > 1}
44 if verbose:
45 print("Doublons trouvés :")
46 pprint.pprint(d)
47 return d
48
49 def run(dir, verbose=False, dry=False):
50 """Do the job sur ``dir``"""
51 dups = finddups(dir, verbose)
52 if not dups:
53 print("Aucun doublon trouvé")
54 return
55 if dry:
56 print("**dry-run**, rien ne sera supprimé")
57 for (_, files) in dups.iteritems():
58 sizes = [os.path.getsize(f) for f in files]
59 msize = min(sizes)
60 keep = files[sizes.index(msize)]
61 removes = [f for f in files if f != keep]
62 if verbose or dry:
63 for f in removes:
64 print("Suppression de %s (doublon de %s)" % (f, keep))
65 if not dry:
66 for f in removes:
67 os.remove(f)
68
69 parser = argparse.ArgumentParser(description="Suppression de mails identiques.")
70 parser.add_argument("-v", "--verbose", help="Afficher ce qui est supprimé", action="store_true")
71 parser.add_argument("-n", "--dry-run", help="Faire semblant", action="store_true")
72 parser.add_argument("dir", help="Le dossier où chercher les doublons", type=str)
73
74 if __name__ == "__main__":
75 args = parser.parse_args()
76 d = run(args.dir, verbose=args.verbose, dry=args.dry_run)