Katal est un projet GPLv3/Python3/CLI/Linux-Windows : il permet de créer un catalogue de fichiers à partir de différentes sources, en filtrant les fichiers à récupérer, en les renommant à la volée; on peut alors étiqueter les fichiers obtenus.
Le répertoire de destination contient les fichiers du catalogue, une base de données, un dossier .trash et un dossier pour les logs. J'ai l'habitude de placer dans le répertoire de destination le script katal.py; ainsi, je déplace le catalogue en même temps que l'outil qui me permet de le gérer.
De l'aide est disponible dans le fichier README.md : voyez ici.
Voyez aussi le résultat de $ katal -h
.
Sommaire
- L'histoire
- Installation
-
Utilisation
- Créer le répertoire de destination, qui contiendra les fichiers du catalogue :
- Placez-vous ensuite à l'intérieur du répertoire de destination.
- À l'intérieur du répertoire de destination, modifier le fichier de configuration ./katal/katal.ini :
- Tester le fichier de configuration ./katal/katal.ini :
- Si vous êtes d'accord, répondez oui en tapant 'y' + entrée :
- Vous pouvez à tout moment afficher ces informations sur le catalogue à l'aide de l'option -ti :
- Vous pouvez enfin étiqueter un ou plusieurs fichiers :
- Vous pouvez aussi :
- Et la suite ?
L'histoire
Un copain m'avait demandé de l'aider à classer des dizaines de milliers de photos tirées de milliers de répertoires différents, mélangées avec toutes sortes de fichiers (textes, vidéos); beaucoup de photos identiques portaient des noms différents.
Je voulais obtenir un catalogue des fichiers :
- qui avaient l'extension de fichiers image (.jpg, .tiff, …) ;
- qui avaient une taille supérieure à 2 Mo pour éliminer les vignettes ;
- sans doublon (=aucun fichier ayant le même contenu qu'un autre) ;
- avec la possibilité d'étiqueter (=avec des tags) les images ;
- avec la possibilité de renommer les fichiers ;
- avec des fichiers de logs verbeux pour garder la trace de mes essais et de mes erreurs ;
- le tout sur Linux/Mac/Windows puisque je passais d'un ordinateur à l'autre.
Installation
$ pip install katal
katal est en effet hébergé sur Pypi.
mais aussi :
$ wget https://raw.githubusercontent.com/suizokukan/katal/master/katal/katal.py
… puisque le projet Katal tient en un seul fichier, katal.py, qui peut être placé dans le répertoire de destination.
Utilisation
Créer le répertoire de destination, qui contiendra les fichiers du catalogue :
$ katal --new=destdir
… et accepter de télécharger le fichier de configuration par défaut qui sera placé dans le répertoire de destination (dans un sous répertoire nommé .katal
)
Placez-vous ensuite à l'intérieur du répertoire de destination.
$ cd destdir
Vous pouvez voir ce que pense Katal de ce répertoire en tapant :
$ katal --infos
À l'intérieur du répertoire de destination, modifier le fichier de configuration ./katal/katal.ini :
Changer la source, par exemple :
[source]
path : ~/masource/photos/
Katal recherchera de manière récursive dans ce répertoire.
Changer le nom des fichiers qui seront copiés dans le répertoire de destination, par exemple :
[target]
name of the target files : INTTIMESTAMP_SIZE__DATABASE_INDEX.SOURCE_EXTENSION2
… pour avoir des fichiers du type 1445584562_123__1.jpg (=timestamp du fichier source, taille du fichier source, index dans la base de données du répertoire de destination)
Changer la fonction d'évaluation permettant de faire le tri entre les fichiers de la source, par exemple :
… si vous voulez les fichiers python du répertoire source :
[source]
eval : sieve1
[source.sieve1]
name : .*\.py$
… si vous voulez les fichiers python du répertoire source faisant plus d'un mégaoctet :
[source]
eval : sieve1
[source.sieve1]
name : .*\.py$
size : >1000000
… si vous voulez les fichiers python du répertoire source faisant plus d'un mégaoctet OU les .jpg :
[source]
eval : sieve1 or sieve2
[source.sieve1]
name : .*\.py$
size : >1000000
[source.sieve2]
name : .*\.jpg$
Tester le fichier de configuration ./katal/katal.ini :
$ katal --select
Katal vous montre alors ce qui se passerait si vous acceptiez la copie de la source vers la destination. Par exemple :
+ selected /home/suizokukan/projets/dysodos/dysodos.py (file selected #1)
- discarded "/home/suizokukan/projets/dysodos/.git/description" : incompatibility with the sieves
- discarded "/home/suizokukan/projets/dysodos/.git/info/exclude" : incompatibility with the sieves
[...]
o everything ok : no anomaly detected. See details above.
o size of the selected file(s) : 3877 bytes
o number of selected files (after discarding 36 file(s)) : 1, 2.70% of the source files.
o required space : 3877 bytes; available space on disk : ~35.62 Go (35619852288 bytes) (ok)
o e.g. … "/home/suizokukan/projets/dysodos/dysodos.py" would be copied as "/home/suizokukan/projets/katal/target2/5474c904__0.py" .
Do you want to add the selected files to the target dictionary (".") ? (y/N)
Si vous êtes d'accord, répondez oui en tapant 'y' + entrée :
… (1/1) copying "/home/suizokukan/projets/dysodos/dysodos.py" to "/home/suizokukan/projets/katal/target2/5474c904__0.py" .
= all files have been copied, let's update the database… =
= … database updated =
Katal affiche automatiquement le contenu du catalogue (ici, un seul fichier) :
= informations about the "." (path: "/home/suizokukan/projets/katal/target2") target directory =
+--------------------+--------------------+------+--------------------+------------------+
| hashid/base64 | name | tags | source name | source date |
+--------------------+--------------------+------+--------------------+------------------+
| […]f8SfE3Tzc+UP0s= | […]/5474c904__0.py | | […]odos/dysodos.py | 2014-11-25 19:23 |
+--------------------+--------------------+------+--------------------+------------------+
Vous pouvez à tout moment afficher ces informations sur le catalogue à l'aide de l'option -ti :
$ katal -ti
(ti : target informations)
=======================================================
=== Katal v.0.1.3 (launched at 2015-10-25 17:19:06) ===
=======================================================
= target directory given as parameter : "." (path : "/home/suizokukan/projets/katal/target2")
= no config file specified on the command line : let's search a config file in the current directory…
* config file name : "/home/suizokukan/projets/katal/target2/.katal/katal.ini" (path : "/home/suizokukan/projets/katal/target2/.katal/katal.ini")
… config file found and read (ok)
= source directory : "~/projets/dysodos" (path : "/home/suizokukan/projets/dysodos")
= informations about the "." (path: "/home/suizokukan/projets/katal/target2") target directory =
+--------------------+--------------------+------+--------------------+------------------+
| hashid/base64 | name | tags | source name | source date |
+--------------------+--------------------+------+--------------------+------------------+
| […]f8SfE3Tzc+UP0s= | […]/5474c904__0.py | | […]odos/dysodos.py | 2014-11-25 19:23 |
+--------------------+--------------------+------+--------------------+------------------+
=== exit (stopped at 2015-10-25 17:19; total duration time : 0:00:00.004414) ===
Vous pouvez enfin étiqueter un ou plusieurs fichiers :
Si vous voulez ajouter le tag "mytag" aux fichiers Python :
$ katal --addtag=mytag --to=*.py
Si vous voulez ajouter le tag "mytag" à un seul fichier :
$ katal --addtag=mytag --to=5474c904__0.py
Vous pouvez aussi :
- supprimer toutes les étiquettes d'un ou plusieurs fichiers (--rmnotags) ;
- supprimer un fichier ou plusieurs fichiers du catalogue (--targetkill) ;
- supprimer les fichiers qui n'ont pas de tags (--rmnotags) ;
- supprimer de la base de données les fichiers qui n'existent pas dans le répertoire de destination (--cleandbrm).
Et d'autres choses encore, accessibles dans le fichier README.md ou en consultant le résultat de $ katal -h
.
Et la suite ?
J'ai essayé d'écrire du code lisible par tous : pylint à 10, documentation abondante, commentaires et documentation en anglais…
Je serais ravi de vos commentaires et de vos suggestions d'amélioration !
Aller plus loin
- projet sur github (396 clics)
- projet sur Pypi (172 clics)
# Suggestion d'amélioration
Posté par fbernard . Évalué à 3.
Google Translate s'est pris les pieds dans le tapis : "doublons" peut se traduire par "doubloons", mais uniquement s'il est question de trésor, ou d'épave de galion. Dans le cas de fichiers, "duplicates" serait plus approprié.
[^] # Re: Suggestion d'amélioration
Posté par Xavier Faure (site web personnel) . Évalué à 1.
Merci !
Trust the Python !
# Questions
Posté par Cascador (site web personnel) . Évalué à 3.
Hello,
Alors déjà super idée ! Et merci pour ce projet !
Ça m'intéresse beaucoup (je précise que j'ai pas encore joué avec) alors j'ai des questions :
- Comment gères-tu les doublons ? Car en plus tu précises (même contenu)
- Des limitations connues (taille de fichiers, caractères qui ne passent pas…) ?
- Vu que tu es parti de 0, il n'y a donc aucun projet que tu pourrais recommander comme "alternative" au tien ? Ceci afin de comparer
- Le logiciel est bien-sûr capable de bosser avec un montage (genre je monte un NAS et je balance le tri en local) ?
- Tu parles d'une base de données, c'est quoi comme base ?
- T'as une roadmap ? C'est quoi la prochaine feature, la prochaine grosse étape ?
Merci, Tcho !
[^] # Re: Questions
Posté par Xavier Faure (site web personnel) . Évalué à 4. Dernière modification le 26 octobre 2015 à 16:50.
Merci pour les encouragements :
Si tu es intéressé, fais-le-moi savoir !
Trust the Python !
[^] # Re: Questions
Posté par Xavier Faure (site web personnel) . Évalué à 1.
Grâce à Cascador, je peux rectifier une erreur quant à l'utilisation de wget pour télécharger Katal :
$wget https://raw.githubusercontent.com/suizokukan/katal/master/katal/katal.py
… est la bonne adresse; celle que je donnais encapsulait le code Python dans du HTML.
Si un admin' pouvait rectifier ma dépêche : merci d'avance !
Trust the Python !
[^] # Re: Questions
Posté par Benoît Sibaud (site web personnel) . Évalué à 4.
Corrigé, merci.
[^] # Re: Questions
Posté par zyphos . Évalué à 3.
Pour les doublons le fait de ne vérifier que les hash n'est pas suffisant, les hash peuvent avoir des collisions.
J'en ai déjà fait les frais, des fichiers effacés par erreur lors d'une déduplication,
merci liten2, https://code.google.com/p/liten2/
En effet, chez liten2 c'est encore pire que de comparer les hash complets, il ne compare que les hash des 16 premiers Ko du chaque fichier.
Je pense que le mieux est:
1. Vérification de la taille des fichiers
2. Si même taille, vérification du hash
3. Si même hash faire une vraie comparaison bit à bit.
[^] # Re: Questions
Posté par Jaimz . Évalué à 2.
La probabilité de trouver une collision en utilisant SHA256 est minuscule.
Même avec un milliard de fichiers elle est inférieure à 1 sur 1060.
La comparaison bit à bit ajouterait beaucoup de lourdeur inutile.
[^] # Re: Questions
Posté par Xavier Faure (site web personnel) . Évalué à 2.
Je pense aussi que la probabilité d'une collision est quasi nulle. Pour mettre tout le monde d'accord, je vais modifier mon code en laissant le choix à l'utilisateur d'exiger ou non une comparaison bit à bit si deux hashs sont identiques.
Merci à tous de ces remarques qui m'aident à améliorer mon code !
Trust the Python !
[^] # Re: Questions
Posté par zyphos . Évalué à 3.
On parle de données (ex: photos de famille), je pense qu'un risque, même très faible, n'est pas acceptable pour des données.
De plus la comparaison bit à bit ne se ferait qu'en cas très rare d'hash identique. Donc, la perte de performance sera très faible et justifiée.
Par contre vérifier la taille des fichiers me semble être vraiment le strict minimum. Bien avant de calculer et comparer un hash.
Pour optimiser le tout, je ne calculerais les "hash"s que si au moins 2 fichiers ont la même taille. Puis évidement ils seraient stockés dans la DB.
[^] # Re: Questions
Posté par Xavier Faure (site web personnel) . Évalué à 2.
Voici que ce j'envisage de faire : stocker dans la base de données la taille, le hash partiel, le hash complet de chaque fichier.
Pour tout nouveau fichier, je vérifie si sa taille correspond à qqc de connu; si c'est le cas, je calcule un hash partiel (sur 1 Mo ?) sur les fichiers qui ont la même taille; si ce hash partiel correspond à qqc dans la base de données, je calcule alors le hash complet. Si le hash complet correspond, normalement j'élimine le fichier source comme doublon; si une option "strict cmp" est activée, je vérifie bit à bit.
Trust the Python !
[^] # Re: Questions
Posté par Faya . Évalué à 1.
Voici une "alternative" en java et libre, si tu veux de l'inspiration : http://evrignaud.github.io/fim/#_why_do_you_need_fim
Par contre ton logiciel a plus de fonctionnalités (tags, recherche)
[^] # Re: Questions
Posté par barmic . Évalué à 4.
Sous unix, commence par regarder les inodes au cas où l'utilisateur a juste créé des liens durs.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Questions
Posté par Xavier Faure (site web personnel) . Évalué à 1.
Merci de cette suggestion, hélas valable uniquement pour Linux. Je vais y réfléchir.
Trust the Python !
[^] # Re: Questions
Posté par Xavier Faure (site web personnel) . Évalué à 1.
Toujours grâce à Cascador, je préciser que sur la majorité des systèmes Linux il faut écrire :
$pip3 install katal
à la place de
$pip install katal
Merci.
Trust the Python !
# Merci !
Posté par flan (site web personnel) . Évalué à 3.
Je note la chose bien précieusement : je vais devoir faire du tri dans pas mal de photos également, avec plein de doublons.
Je ne sais pas encore quand je m'y collerais, mais ça va m'être bien utile !
[^] # Re: Merci !
Posté par Xavier Faure (site web personnel) . Évalué à 2.
N'hésite pas à me poser des questions si la doc' n'est pas assez claire. Ca me ferait très plaisir de t'aider… ou d'incorporer tes suggestions.
Trust the Python !
# Splendide !
Posté par Serge Julien . Évalué à 4.
Mais c'est maaaaaaagnifique, ça! Ça colle pile-poil à mes besoins.
J'ai une énorme opération de tri/étiquetage/chasse aux doublons à faire au début de l'année prochaine, je m'étais lancé dans l'écriture d'un bidule similaire, mais Katal va bien plus loin…
Merci!
[^] # Re: Splendide !
Posté par Xavier Faure (site web personnel) . Évalué à 2.
Merci de tes encouragements; je pensais être le seul à utiliser Katal mais si d'autres que moi en ont besoin, je vais continuer à travailler dessus. Prochaine petite étape, sans doute pour la fin de la semaine : la possibilité de trouver les fichiers ayant un certain tag.
Si vous avez des suggestions, je suis preneur !
Trust the Python !
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.