Created
February 28, 2017 09:36
-
-
Save alexwlchan/e6b35ef3e5cb658d8047deadee6cf629 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- encoding: utf-8 -*- | |
"""Generate unique filenames for a file you're about to create. | |
The functions in this snippet are useful for ensuring you don't inadvertently | |
create a file that replaces an existing file. Given a name, they try to | |
find a similar name that doesn't already exist on the disk. | |
This code isn't safe from race conditions -- if a file pops into existence | |
between the check and the write, you could still lose data -- but it's a | |
good start. If you really want to be sure a file doesn't exist when you | |
write to it, use the 'x' mode for `open()` in Python 3: | |
https://alexwlchan.net/2016/03/exclusive-create-python/ | |
""" | |
import os | |
import random | |
import string | |
def generate_variations(path): | |
"""Given a path, generate variations that add a few characters of random | |
noise to the path. | |
:param path: Starting path. | |
""" | |
# Implementation note: the 'noise' is five characters of alphanumeric | |
# text added before the file extension. Including uppercase and lowercase, | |
# this allows up to 62^5 = 9e9 possible variations. That's plenty for | |
# most use cases. Add more characters if you're feeling picky. | |
yield path | |
base, ext = os.splitext(path) | |
while True: | |
noise = ''.join([ | |
random.choice(string.ascii_letters + string.digits) | |
for _ in range(5) | |
]) | |
yield '%s_%s%s' % (base, noise, ext) | |
def choose_unique_filename(path): | |
"""Given a filename, return a variation on that filename that doesn't | |
already exist on disk.""" | |
for new_path in generate_variations(path): | |
if not os.path.exists(new_path): | |
return new_path |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment