Python – Tri de fichiers

Sur le forum d’ubuntu-fr, il y a eu une demande qui demandait la création d’un script. Pour résumer, il y avait plus de 300 Go de données séparé en 3900 répertoires, et il fallait trier le tout pour ranger les fichiers selon leurs types. Les premières solutions envisagées l’ont été avec bash, mais, bien que je ne doute pas de la faisabilité de la chose, il m’a semblé plus simple de faire ça en python.

Comme Ubuntu utilise encore python 2, j’ai choisi cette version (mais c’est très simplement adaptable en python 3). Voilà le texte de présentation que j’ai posté avec mon programme :

Son fonctionnement est très simple : il suffit de le lancer en ligne de commande avec en argument le chemin du répertoire à traiter. Ensuite, il se lance récursivement pour récupérer tous les fichiers présents dans les sous-répertoires et les déplacer dans des dossiers nommés selon les extensions. Ensuite, une fois que les déplacements ont été fait, il supprime les répertoires vides. Il gère aussi les doublons (il ajoute (1), (2), etc. à la fin des fichiers qui ont les mêmes noms). J’ai fait quelques tests, il semble bien fonctionner, mais ça risque de prendre pas mal de temps si tu le lances sur 300 Go de données. Par contre, c’est un script puissant, qui peut faire des dégâts si tu le lances sur le mauvais répertoire. Sois donc attentif avant de le lancer. Par ailleurs, je ne peux pas garantir qu’il fonctionne parfaitement (dans le pire des cas, tu peux perdre des fichiers qui étaient dans le répertoire à traiter. Normalement, il n’y a aucun risque pour ton ordinateur).

Pour l’instant, je vois deux pistes d’amélioration : j’aurais pu utiliser os.walk() pour naviguer dans les sous-répertoires et directement sélectionner les éléments selon leurs types (répertoire ou fichier), et j’aurais pu trouver une meilleure solution que de me baser sur l’extension pour trouver le nom de fichier (surtout qu’avec ma solution, les fichiers en .tar.gz seront rangés dans le répertoire gz). Mais bon, je pense que ça fonctionne assez bien comme ça…

Voilà donc le script (qui est bien commenté et facile à comprendre) :

#!/usr/bin/env python
#coding: utf-8

import os
import shutil
import sys

# Vérification des arguments
if (len(sys.argv) != 2):
    sys.exit("Syntaxe: ./script.py '/chemin/vers/repertoire'")
if not os.path.isdir(sys.argv[1]):
    sys.exit("Le chemin demandé n'existe pas")

chemin = sys.argv[1]

# cheminroot = répertoire dans lequel les fichiers sont déplacés
cheminroot = os.path.abspath(os.path.join(chemin, '..'))
cheminroot = os.path.join(cheminroot,'fichiers-trié')

# Fonction pour pouvoir déplacer les doublons : on ajoute (1), (2), etc.
# à la fin des fichiers ayant les mêmes noms
def doublon(dst):
    fileName, fileExtension = os.path.splitext(dst)
    i = 1
    while os.path.isfile(dst):
        fileName += '('+ str(i)+ ')'
        dst = fileName + fileExtension
        i+=1
    return dst

def tri(chemin):
    for f in os.listdir(chemin):
        src = chemin
        src = os.path.join(chemin,f)

        # si l'élément considéré est un répertoire non vide, on appelle
        # récursivement la fonction. S'il est vide, on le supprime.
        if os.path.isdir(src):
            if not os.listdir(src):
                os.rmdir(src)
            else:
                tri(src)

        # Si l'élément est un fichier, on récupère son extension
        else:
            fileName, fileExtension = os.path.splitext(f)
            fileExtension = fileExtension[1:]

            # On créé un répertoire pour y déplacer les fichiers ayant
            # cette extention
            if fileExtension:
                dst = os.path.join(cheminroot,fileExtension)
            else:
                dst = os.path.join(cheminroot,'sansExtension')
            if not os.path.isdir(dst):
                print 'Création de ', dst
                os.makedirs(dst)

            # On déplace le fichier avec gestion des doublons
            if not os.path.isfile(dst+'/'+f):
                print 'mv', src, ' ', dst
                shutil.move(src, dst)
            else:
                dst = doublon(dst+'/'+f)
                print 'mv', src, ' ', dst
                shutil.move(src, dst)

            # On supprime les répertoires une fois qu’ils sont vides
            parentFolder = os.path.abspath(os.path.join(src, '..'))
            if not os.listdir(parentFolder):
                os.rmdir(parentFolder)

# Premier appel de la fonction
tri(chemin)
Vus : 840
Publié par Shanx : 16