Supprimer les fichiers doublons de votre système avec RMLINT

Les technologies de stockage, les supports, avec leurs coûts de plus en plus faibles pour des capacités de plus en plus élevées, ont permis l’explosion du nombre des fichiers présents sur nos systèmes.

On copie d’un côté, on modifie de l’autre, on oublie ce que l’on stocke, on sauvegarde, plus de place ? pas de soucis, on transfert sur un autre disque dur … Le temps passant, les problèmes d’organisation de fichiers, apparaissent. Comment repérer photos, musiques, vidéos en double ? Des fichiers, souvent les mêmes, copiés sur plusieurs disques, partitions ou répertoires, comment les rassembler en une seule arborescence ? Comment libérer de la place ?

Il y a toujours la bonne vieille méthode manuelle: regarder chaque photos en face à face, lancer les vidéos et regarder la durée, faire un diff sur les fichiers textes, comparer les tailles dans son explorateur… Ou bien utiliser un outil qui sait faire le job.
rmlint est un de ces outils. En ligne de commande, il vous permet d’identifier les fichiers doublons, fichiers et répertoires vides, liens cassés, binaires non strippés, fichiers temporaires, etc …

Dans cette catégorie il existe d’autres outils connus comme fdupes, fslint ou rdfind mais rmlint possède des atouts: la rapidité, la rapidité, la rapidité et la performance grâce à un algorithme qui favorise la charge processeur plutôt que les entrées | sorties. C’est aussi un outil très souple qui possède d’astucieuses options.

rmlint: https://github.com/sahib/rmlint

Lancement

Si vous ne spécifiez pas de répertoire(s) ou de fichiers en argument, rmlint parcourra le répertoire courant.

rmlint

Vous pouvez préciser un chemin:

rmlint /chemin/

plusieurs chemins:

rmlint /chemin_1/ /chemin_2/ /chemin_3/sous_repertoire3/

mixer répertoires et fichiers:

rmlint /chemin_1/ /chemin_1/un_fichier.txt /chemin_2/un_autre_fichier.txt

Fichier d’origine et doublons

Quand rmlint rencontre plusieurs fichiers identiques il en désigne un comme le fichier d’origine et les autres sont considérés comme des copies. Le traitement aura lieu par défaut sur les copies de ce fichier. Le fichier original est celui qui possède le plus petit numéro d’inode. rmlint considère, sur une même partition, que le fichier avec le numéro d’inode le plus petit est celui qui a été créé en premier. Du point de vue des systèmes de fichiers ce n’est pas une règle de fonctionnement stricte car un fichier est copié là où il peut l’être.

On peut forcer rmlint à prendre comme original le premier fichier rencontré dans un répertoire précis en mettant // devant son chemin. Utile si plusieurs répertoires se trouve sur des partitions différentes.

rmlint /chemin_1/ ///chemin_2/ /chemin_3/sous_repertoire3/

Dans ce cas le premier fichier rencontré dans /chemin_2 et ayant le plus petit numéro d’inode sera considéré comme l’original.

Actions possibles sur les fichiers

Avertissement: Comme tous les outils de gestion de fichiers, il est nécessaire de faire preuve d’une extrême prudence et de réfléchir avant d’exécuter ou de valider une action. Les systèmes UNIX considèrent que vous savez ce que vous faîtes (et c’est aussi pour cela qu’on les aime ^^).

Générer un script de nettoyage et un fichier de log

C’est le comportement par défaut de rmlint. Il ne modifie pas votre système, il génère une sortie, un fichier de log et un script shell dans le répertoire courant de l’exécution.

rmlint /tmp/testdir/

Sortie sous la forme d’une liste en couleur avec des informations:

# Duplicate(s):
   ls /tmp/testdir/links_test/hard_3
   rm /tmp/testdir/links_test/hard_2
   rm /tmp/testdir/links_test/orig
   rm /tmp/testdir/test/dir2/oof
   ls /tmp/testdir/test/dir1/bar
   rm /tmp/testdir/test/dir2/bar
   ...

=> In total 32 files, whereof 17 are duplicate(s)
=> Totally  78 B  [78 Bytes] can be removed.
=> Nothing removed yet!

A log has been written to rmlint.log.
A ready to use shellscript to rmlint.sh.

Le fichier de log rmlint.log détaille pour chaque fichier trouvé une ligne d’information.

Exemple:

DUPL//c16898f0bba213d47ea031fe3e707977///tmp/testdir/recursed_b/one_the_second//4//28//19487//

Cette ligne est composée d’un indicateur:

EDIR: Répertoire vide
ZERO: Fichier vide
DUPL: Fichie en double
...

De la somme de contrôle md5, du chemin, de la taille, de l’identifiant du périphérique de stockage et du numéro d’inode.

Le script shell rmlint.sh créé comprend toutes les instructions pour supprimer les fichiers. Il est nécessaire de le parcourir pour l’ajuster afin de modifier ou supprimer des lignes.

Exemple de lignes dans le script rmlint.sh:

echo  '/tmp/testdir/recursed_b/one' # original
rm -f '/tmp/testdir/recursed_b/one_the_second' # duplicate
rm -f '/tmp/testdir/recursed_a/one' # duplicate

echo affichera sur la sortie standard le chemin du fichier considéré comme l’original. Ce fichier restera en place dans le système de fichiers. Les 2 lignes suivantes supprimeront 2 doublons.

Les modifications les plus courantes sont de supprimer des lignes pour préserver les fichiers ou modifer le choix du fichier original en modifiant sa ligne de commande.

Exemple de modifications du fichier précédent:

rm -f  '/tmp/testdir/recursed_b/one' # l'original défini sera supprimé
echo '/tmp/testdir/recursed_b/one_the_second' # ce doublon sera préservé
# la 3ème ligne est supprimée pour préserver le fichier /tmp/testdir/recursed_a/one

Vous pouvez ensuite l’exécuter pour lancer le traitement em masse sur vos fichiers.

./rmlint.sh

Sortie

usage: ./rmlint.sh options

OPTIONS:
-h      Show this message
-d      Do not ask before running
-x      Keep rmlint.sh and rmlint.log
This script will delete certain files rmlint found.
It is highly advisable to view the script (or log) first!

Execute this script with -d to disable this message
Hit enter to continue; CTRL-C to abort immediately

Appuyez sur ENTRÉE pour confirmer ou CTRL-C pour annuler l’opération..

Afficher les fichiers et ne rien faire

Cette commande affiche sur la sortie la liste des fichiers concernés. Votre système n’est pas modifié.

rmlint -o -v1 /tmp/testdir/

-o : Sans argument, cette option ne génère ni le script ni le fichier de log.
-v1 : Mode verbeux 1 qui affiche uniquement les fichiers, sans couleur.

Sortie:

# Duplicate(s):   rm /tmp/testdir/recursed_b/one_the_second
   rm /tmp/testdir/recursed_a/one
   rm /tmp/testdir/links_test/hard_2
   rm /tmp/testdir/links_test/orig
   rm /tmp/testdir/links_test/hard_1
   rm /tmp/testdir/test/dir1/lol
   rm /tmp/testdir/test/dir1/foo
   rm /tmp/testdir/test/dir1/oof
   rm /tmp/testdir/test/dir2/ror
   rm /tmp/testdir/test/dir2/foo
   rm /tmp/testdir/test/dir2/oof
   rm /tmp/testdir/test/dir2/bar
   rm /tmp/testdir/test/dir2/baz
   rm /tmp/testdir/twice_one
   rm /tmp/testdir/two
   rm /tmp/testdir/recursed_b/three
   rm /tmp/testdir/with spaces b

Remplacer les doublons par un lien symbolique

Chaque doublon est remplacé par un lien symbolique à l’exécution de la commande. Votre système est modifié.

rmlint --mode link /tmp/testdir/

--mode : Permet de choisir le mode d’action ici link

Sortie:

# Duplicate(s):
   ln -s "/tmp/testdir/recursed_b/one" "/tmp/testdir/recursed_b/one_the_second"
   ln -s "/tmp/testdir/recursed_b/one" "/tmp/testdir/recursed_a/one"
   ln -s "/tmp/testdir/links_test/hard_3" "/tmp/testdir/links_test/hard_2"
   ...

Les fichiers script et log sont aussi créés. Si vous exécutez le script, vos liens fraîchement créés seront supprimés.

Pour éviter le fichier de log et le script, utilisez l’option -o sans argument.

rmlint -o --mode link /tmp/testdir/

Supprimer les fichiers sans confirmation

La méthode radicale. A l’exécution de la commande les fichiers seront supprimés. Votre système est modifié.

rmlint -o --mode noask /tmp/testdir/

--mode noask : Choisir le mode d’action sans confirmation.
-o : Sans argument, cette option ne génère ni le script ni le fichier de log.

Pour une intégration dans un de vos script, cette commande s’accorde bien avec le mode verbeux silencieux -v0.

Sortie:

# Duplicate(s):   rm -rf "/tmp/testdir/test/dir1/foo"
   rm -rf "/tmp/testdir/test/dir1/oof"
   rm -rf "/tmp/testdir/test/dir2/ror"
   rm -rf "/tmp/testdir/test/dir2/oof"
   ...

=> In total 34 files, whereof 17 are duplicate(s)
=> Totally  78 B  [78 Bytes] can be removed.

Demander l’action pour chaque fichier

La commande inverse de la précédente. Dans un mode interactif, rmlint sollicite l’utilisateur pour chaque fichier. Le choix se fait par une lettre:

k - (keep) pour garder le fichier
d - (delete) supprimer le fichier
i - (info) afficher plus d’informations sur les fichiers
l - (link) remplacer le fichier par un lien symbolique
q - (quit) quitter complètement rmlint
h - (help) afficher de l’aide

rmlint -o --mode ask /tmp/testdir

--mode ask : Choisir le mode d’action interactif.
-o : Ne génère ni le script de nettoyage ni le fichier de log.

Sortie:

:: '/tmp/testdir/recursed_b/one_the_second' same as '/tmp/testdir/recursed_b/one' [h for help]
:: k       
:: '/tmp/testdir/recursed_a/one' same as '/tmp/testdir/recursed_b/one' [h for help]
:: d
:: '/tmp/testdir/links_test/hard_2' same as '/tmp/testdir/links_test/hard_3' [h for help]
:: l
...

Exécuter une action définie sur chaque fichier

Dans ce mode c’est vous qui définissez les commandes à exécuter sur les fichiers. rmlint ne modifie pas votre système mais adapte le script sh selon vos indications.

Exemple:

rmlint --mode cmd -C "ls -la '<orig>'" -c "echo '<dupl>' # same as '<orig>'" /tmp/testdir/

Les tags <orig> et <dupl> seront remplacés dans le script par les fichiers et leurs chemins respectifs.

--mode cmd : Choisir le mode d’action commande.
-c : Ligne de commande pour chaque(s) fichier(s) doublon(s).
-C : Ligne de commande pour chaque fichier d’origine. Le tag <dupl> n’est pas pris en compte avec cette option.

Sortie:

# Duplicate(s):/tmp/testdir/recursed_b/one_the_second
/tmp/testdir/recursed_a/one
/tmp/testdir/links_test/hard_2
/tmp/testdir/links_test/orig
/tmp/testdir/links_test/hard_1
/tmp/testdir/test/dir1/lol
/tmp/testdir/test/dir1/foo
...

=> In total 34 files, whereof 17 are duplicate(s)
=> Totally  78 B  [78 Bytes] can be removed.

Exemple de lignes générées dans le script par la commande ci-dessus:

...
ls -la '/tmp/testdir/recursed_b/one'
echo '/tmp/testdir/recursed_b/one_the_second' # same as '/tmp/testdir/recursed_b/one'
echo '/tmp/testdir/recursed_a/one' # same as '/tmp/testdir/recursed_b/one'
...

A propos des faux positifs

Avec rmlint les faux positifs sont très très rares car les il faudrait que les fichiers possèdent la même taille avec une empreinte et une somme de contrôle md5 identiques.

Même si la probabilité est proche de 0 il existe l’option paranoïaque -p qui vous garantie le résultat à 100%. Comment ? En appliquant une comparaison byte à byte. La contre partie sera une extrême lenteur d’exécution.

Utiliser les expressions régulières

rmlint vous permet d’utiliser les expressions régulières pour limiter son action aux répertoires et aux fichiers correspondant à un motif (une chaîne de caractères).

 rmlint -r^on /tmp/testdir/

-r : Permet de définir un motif pour les fichiers. Dans l’exemple, les fichiers commençant par on

Sortie:

# Duplicate(s):
   ls /tmp/testdir/recursed_b/one
   rm /tmp/testdir/recursed_b/one_the_second
   rm /tmp/testdir/recursed_a/one

=> In total 3 files, whereof 2 are duplicate(s)
=> Totally  8 B  [8 Bytes] can be removed.
=> Nothing removed yet!

Pour inverser le filtre, c’est à dire ne pas prendre en compte un motif, on utilise l’option -i.

rmlint -i -r^on /tmp/testdir/

Dans cet exemple rmlint traitera normalement tous les fichiers et ignorera ceux commençant par on.

-R : Définir un motif pour les répertoires.
-e : Force à respecter la casse pour le motif. FIChIeR sera différent de fichier

Autres options disponibles

-t : Augmente le nombre de threads. Permet d’augmenter la vitesse d’exécution de rmlint en augmentant la charge du processeur. Par défaut ce nombre est fixé à 16, suffisant pour une utilisation normale.

-d : Permet de définir la profondeur maximale des répertoires. Par défaut elle est illimitée.
Exemple pour limiter l’action uniquement à la racine, le premier niveau d’un répertoire:

rmlint -d1 /tmp/testdir/

Certaines options sont activées par défaut. Nul besoin de les préciser. Par exemple -y permet de chercher les répertoires vides et -k les fichiers vides. Par contre, pour désactiver ce comportement il suffit de passer l’option en majuscule. Exemple d’une recherche sans prendre en compte les répertoires et les fichiers vides :

rmlint -Y -K /tmp/testdir/

-o : Cette option déjà rencontrée sert aussi à spécifier le nom utilisé pour nommer le fichier de log et le script. Exemple:

rmlint -omonfichier /tmp/testdir/

Le fichier de log se nommera monfichier.log et le fichier de script monfichier.sh.

-G : Cherche aussi parmi les fichiers et les répertoires cachés.

-v : Définir le mode verbeux pour la sortie standard.

0 : pas de sortie
1 : + affiche les erreurs (s’il y en a) et les correspondances - sans couleur
2 : + affiche les alertes éventuelles - en couleur (mode par défaut)
3 : + des informations supplémentaires
4 : + affiche le contenu du log sur la sortie
5 : + affiche le contenu du script sur la sortie
6 : + une sortie à la manière de rdfind

Découvrir les autres options grâce au manuel:

man rmlint

Conclusion

rmlint est un outil très spécialisé, très efficace, donc très appréciable et qui mérite d’être adopté. Apprendre à l’utiliser, le lancer régulièrement, facilitera la gestion de vos fichiers, permettra de maintenir et de garantir la bonne santé de vos systèmes de fichiers - tout économisant votre temps.

Grâce au travail de Christopher, son développeur, rmlint a bénéficié depuis ses débuts de nombreuses améliorations et optimisations. Christopher est particulièrement actif et à l’écoute sur ses projets alors n’hésitez pas à lui faire part de vos suggestions et autres remontées (bugs?). Je vous encourage aussi à le remercier pour son travail via Flattr.

Plus d’information

rmlint: https://github.com/sahib/rmlint
Forum Archlinux: https://bbs.archlinux.org/viewtopic.php?id=115441

Si vous appréciez rmlint découvrez libglyr, du même auteur, pour récupérer les métadatas de vos musiques. http://www.0x2501.org/b/201X/LYhJNA

fslint: http://www.pixelbeat.org/fslint/
fdupes: http://code.google.com/p/fdupes/
rdfind: http://rdfind.pauldreik.se/