Petit snippet pour obtenir un nom de fichier unique en Python 10


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.

10 thoughts on “Petit snippet pour obtenir un nom de fichier unique en Python

Leave a comment

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.