Sam & Max » filename http://sametmax.com Du code, du cul Sat, 07 Nov 2015 10:56:13 +0000 en-US hourly 1 http://wordpress.org/?v=4.1 Petit snippet pour obtenir un nom de fichier unique en Python 10 http://sametmax.com/petit-snippet-pour-obtenir-un-nom-de-fichier-unique-en-python/ http://sametmax.com/petit-snippet-pour-obtenir-un-nom-de-fichier-unique-en-python/#comments Mon, 24 Feb 2014 12:03:11 +0000 http://sametmax.com/?p=9228 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.

]]>
http://sametmax.com/petit-snippet-pour-obtenir-un-nom-de-fichier-unique-en-python/feed/ 10