10 — Script de rangement de fichiers
Niveau requis : 5 (pathlib, fichiers) / Difficulté : 3/5 / Durée estimée : 2–3 h
Objectif
Un script qui range un dossier en désordre (typiquement Downloads) : il classe les fichiers dans des sous-dossiers par type (images/, documents/, archives/, autres/…) selon leur extension.
python organize.py C:\Users\moi\Downloads
[SIMULATION] photo.jpg -> images/
[SIMULATION] rapport.pdf -> documents/
[SIMULATION] setup.exe -> programmes/
12 fichiers a deplacer. Relance avec --apply pour executer.
⚠️ C'est le premier projet qui MODIFIE de vrais fichiers sur ta machine. Un bug ici ne fait pas un traceback : il déplace ou écrase TES fichiers. D'où la règle absolue de ce projet : le mode simulation (dry-run) est le mode par défaut, et rien n'est déplacé tant qu'on ne passe pas --apply explicitement. Tous les outils sérieux qui touchent au système fonctionnent ainsi. C'est LA compétence enseignée ici — plus importante que pathlib lui-même.
Notions utilisées
pathlib.Path:iterdir(),suffix,name,is_file(),mkdir(),exists()— niveau 5- Déplacement :
Path.rename()(oushutil.move) — niveau 5 - Dictionnaire extension → catégorie — niveau 3
- Arguments de ligne de commande :
sys.argv— niveau 5 - Booléen de contrôle
applypropagé dans le code — niveau 4
Cahier des charges
- Fichier
organize.py, appelé avec le dossier cible en argument :python organize.py <dossier>(simulation) oupython organize.py <dossier> --apply(exécution réelle). - Sans argument, ou si le dossier n'existe pas : message d'usage clair, code de sortie non nul, et surtout AUCUNE action.
- Mapping minimum : images (
.jpg .jpeg .png .gif), documents (.pdf .docx .txt .md), archives (.zip .rar .7z), tout le reste →autres/. Le mapping est un dict en haut du fichier, extensible sans toucher à la logique. - Extensions insensibles à la casse (
.JPG=.jpg). - Le script ignore les dossiers (dont ceux qu'il a créés) et lui-même le cas échéant.
- En simulation : chaque ligne affiche
[SIMULATION], source et destination, puis le total. En--apply: les sous-dossiers sont créés au besoin et les fichiers déplacés, avec un récapitulatif. - Collision : si
images/photo.jpgexiste déjà, ne JAMAIS écraser — renommer enphoto_1.jpg,photo_2.jpg, etc.
Étapes de construction
- Crée d'abord un dossier de test
test_folder/avec une dizaine de faux fichiers de types variés (tu peux les créer en Python :Path("test_folder/photo.jpg").touch()…). Tu ne pointeras le script sur un VRAI dossier qu'à la toute fin. Écris ensuiteorganize.pyqui liste les fichiers du dossier passé en argument (sys.argv[1],iterdir()). - Ajoute la validation : argument manquant ou dossier inexistant → message d'usage +
sys.exit(1). Teste les deux cas. - Ajoute le dict
CATEGORIESet une fonctionget_category(path)basée surpath.suffix.lower(). Affichefichier -> categoriepour chaque fichier. Vérifie chaque classement à l'œil. - Implémente la simulation complète : lignes
[SIMULATION] source -> destination, total, et le message « relance avec --apply ». À ce stade le script est déjà UTILE et ne présente aucun risque. - Détecte le flag
--applydanssys.argv. Implémente le déplacement réel :mkdir(exist_ok=True)pour la catégorie, puisrename(). Lance surtest_folder/uniquement. Vérifie le résultat, recrée le dossier de test, relance. - Gère les collisions : fonction
unique_destination(path)qui suffixe_1,_2… tant que la cible existe. Teste en mettant deux fois le même nom de fichier dans deux catégories… puis en relançant le script deux fois. - Test final sur un vrai dossier : d'abord en simulation, LIS chaque ligne, puis
--applyseulement si tout est correct. C'est le workflow que tu garderas à vie.
Extensions possibles
- Option
--by-date: classer en sous-dossiers2026-07/selon la date de modification (path.stat().st_mtime, moduledatetime). - Journal des déplacements dans un fichier
organize_log.txt(date, source, destination) — indispensable pour retrouver un fichier « disparu ». - Mode
--undoqui rejoue le journal à l'envers. Difficile et instructif : tu comprendras pourquoi les vrais outils gardent des logs. - Config du mapping dans un
categories.jsonexterne.
Erreurs fréquentes sur ce projet
- Tester directement sur son vrai dossier Downloads. L'erreur n'est pas technique, elle est méthodologique — et c'est la plus grave des cinq. Dossier de test d'abord, toujours.
- Écraser en cas de collision :
rename()vers une cible existante écrase silencieusement sur certains systèmes et lèveFileExistsErrorsur d'autres (Windows). Dans les deux cas c'est ton problème à gérer, pas celui de Python. - Itérer et déplacer en même temps : modifier le contenu d'un dossier pendant qu'on l'itère avec
iterdir()peut produire des résultats surprenants. Collecte D'ABORD la liste (list(folder.iterdir())), agis ENSUITE. path.suffixgarde le point (".jpg", pas"jpg") et est sensible à la casse. Les deux oublis classiques du mapping qui « ne matche rien ».- Le script se range lui-même (si
organize.pyest dans le dossier cible) ou range ses propres sous-dossiers de catégories au deuxième lancement. D'oùis_file()+ exclusion explicite.
Critères de réussite
- Sans
--apply, AUCUN fichier n'est déplacé, quel que soit le scénario (vérifié aveciterdir()avant/après). - La simulation liste exactement ce que
--applyferait. - Les collisions produisent
nom_1.ext, jamais d'écrasement. -
.JPGet.jpgfinissent au même endroit. - Relancer le script deux fois de suite est sans danger (idempotent).
- Argument manquant/dossier inexistant : message d'usage, aucune action.
Commit conseillé
git add projects/mini-projects/10-script-rangement-fichiers/
git commit -m "project: add file organizer script"
Puis entrée de journal + git push. Ne committe PAS ton dossier de test plein de faux fichiers (test_folder/ dans .gitignore).