PROJET AUTOBLOG


Sam & Max: Python, Django, Git et du cul

Site original : Sam & Max: Python, Django, Git et du cul

⇐ retour index

Petit snippet pour obtenir un nom de fichier unique en Python

lundi 24 février 2014 à 13:03

Bidouillerie du jour, bonjour.

import re
import os
 
def get_unique_path(path):
 
    # si le nom de fichier existe, on en cherche un autre
    while os.path.exists(path):
        # on vire l'extension
        base, ext = os.path.splitext(path)
        try:
            # on extrait le compteur si il existe
            base, counter, _ = re.split(r" \((\d+)\)$", base)
        except ValueError:
            counter = 0
 
        # on reconstruit le path
        path = "%s (%s)%s" % (base, int(counter) + 1, ext)
 
    return path

Le plus gros de l’astuce est dans :

base, counter, _ = re.split(r" \((\d+)\)$", base)

\((\d+)\)$ va matcher ‘espace(un nombre)’ à la fin d’une chaîne et r.split va retourner soit ['le chemin complet'] si il n’y a pas de compteur, soit ['base', 'compteur', ''] si il y en a un.

Du coup on unpack tout ça, _ étant utilisé pour signaler une variable inutilisée par convention et on a notre compteur, prêt à être incrémenté.

A l’usage, ça donne ça dans ipython :

>>> !rm /tmp/test*
>>> get_unique_path('/tmp/test.txt')
u'/tmp/test.txt'
>>> get_unique_path('/tmp/test.txt')
u'/tmp/test.txt'
>>> !touch /tmp/test.txt
>>> get_unique_path('/tmp/test.txt')
u'/tmp/test (1).txt'
>>> !touch "/tmp/test (1).txt"
>>> get_unique_path('/tmp/test.txt')
u'/tmp/test (2).txt'
>>> get_unique_path('/tmp/test (101).txt')
u'/tmp/test (101).txt'
>>> !touch '/tmp/test (101).txt'
>>> get_unique_path('/tmp/test (101).txt')
u'/tmp/test (102).txt'
>>> get_unique_path('/tmp/test')
u'/tmp/test'
>>> !touch /tmp/test
>>> get_unique_path('/tmp/test')
u'/tmp/test (1)'
>>> get_unique_path('/tmp/.test')
u'/tmp/.test'
>>> !touch "/tmp/.test"
>>> get_unique_path('/tmp/.test')
u'/tmp/.test (1)'
>>> get_unique_path('/tmp/test.path.text')
u'/tmp/test.path.text'
>>> !touch '/tmp/test.path.text'
>>> get_unique_path('/tmp/test.path.text')
u'/tmp/test.path (1).text'
>>> get_unique_path('/tmp/test.path (1)(1) (1).text')
u'/tmp/test.path (1)(1) (1).text'
>>> !touch '/tmp/test.path (1)(1) (1).text'
>>> get_unique_path('/tmp/test.path (1)(1) (1).text')
u'/tmp/test.path (1)(1) (2).text'

Bien entendu, si vos fichiers ne seront jamais visibles par l’utilisateur, il vaut mieux se simplifier la vie et utiliser uuid.uuid4().

Je pense qu’après le dossier sur les tests unitaires, je ferai un dossier regex. Aux alentours de 2018.

flattr this!