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.
