Create file but if name exists add number

后端 未结 14 1964
醉话见心
醉话见心 2020-12-04 18:08

Does Python have any built-in functionality to add a number to a filename if it already exists?

My idea is that it would work the way certain OS\'s work - if a file

相关标签:
14条回答
  • 2020-12-04 18:44

    This works for me. The initial file name is 0.yml, if it exists, it will add one until meet the requirement

    import os
    import itertools
    
    def increment_filename(file_name):
        fid, extension = os.path.splitext(file_name)
    
        yield fid + extension
        for n in itertools.count(start=1, step=1):
            new_id = int(fid) + n
            yield "%s%s" % (new_id, extension)
    
    
    def get_file_path():
        target_file_path = None
        for file_name in increment_filename("0.yml"):
            file_path = os.path.join('/tmp', file_name)
            if not os.path.isfile(file_path):
                target_file_path = file_path
                break
        return target_file_path
    
    0 讨论(0)
  • 2020-12-04 18:46

    In a way, Python has this functionality built into the tempfile module. Unfortunately, you have to tap into a private global variable, tempfile._name_sequence. This means that officially, tempfile makes no guarantee that in future versions _name_sequence even exists -- it is an implementation detail. But if you are okay with using it anyway, this shows how you can create uniquely named files of the form file#.pdf in a specified directory such as /tmp:

    import tempfile
    import itertools as IT
    import os
    
    def uniquify(path, sep = ''):
        def name_sequence():
            count = IT.count()
            yield ''
            while True:
                yield '{s}{n:d}'.format(s = sep, n = next(count))
        orig = tempfile._name_sequence 
        with tempfile._once_lock:
            tempfile._name_sequence = name_sequence()
            path = os.path.normpath(path)
            dirname, basename = os.path.split(path)
            filename, ext = os.path.splitext(basename)
            fd, filename = tempfile.mkstemp(dir = dirname, prefix = filename, suffix = ext)
            tempfile._name_sequence = orig
        return filename
    
    print(uniquify('/tmp/file.pdf'))
    
    0 讨论(0)
  • 2020-12-04 18:46

    A little bit later but there is still something like this should work properly, mb it will be useful for someone.

    You can use built-in iterator to do this ( image downloader as example for you ):

    def image_downloader():
    
            image_url = 'some_image_url'
    
            for count in range(10):
                image_data = requests.get(image_url).content
    
                with open(f'image_{count}.jpg', 'wb') as handler:
                    handler.write(image_data)
    

    Files will increment properly. Result is:

    image.jpg
    image_0.jpg
    image_1.jpg
    image_2.jpg
    image_3.jpg
    image_4.jpg
    image_5.jpg
    image_6.jpg
    image_7.jpg
    image_8.jpg
    image_9.jpg
    
    0 讨论(0)
  • 2020-12-04 18:48

    I was trying to implement the same thing in my project but @unutbu's answer seemed too 'heavy' for my needs so I came up with following code finally:

    import os
    index = ''
    while True:
        try:
            os.makedirs('../hi'+index)
            break
        except WindowsError:
            if index:
                index = '('+str(int(index[1:-1])+1)+')' # Append 1 to number in brackets
            else:
                index = '(1)'
            pass # Go and try create file again
    

    Just in case someone stumbled upon this and requires something simpler.

    0 讨论(0)
  • 2020-12-04 18:48

    I found that the os.path.exists() conditional function did what I needed. I'm using a dictionary-to-csv saving as an example, but the same logic could work for any file type:

    import os 
    
    def smart_save(filename, dict):
        od = filename + '_' # added underscore before number for clarity
    
        for i in np.arange(0,500,1): # I set an arbitrary upper limit of 500
            d = od + str(i)
    
            if os.path.exists(d + '.csv'):
                pass
    
            else:
                with open(d + '.csv', 'w') as f: #or any saving operation you need
                    for key in dict.keys():
                        f.write("%s,%s\n"%(key, dictionary[key]))
                break
    

    Note: this appends a number (starting at 0) to the file name by default, but it's easy to shift that around.

    0 讨论(0)
  • 2020-12-04 18:49

    I've implemented a similar solution with pathlib:

    Create file-names that match the pattern path/<file-name>-\d\d.ext. Perhaps this solution can help...

    import pathlib
    from toolz import itertoolz as itz
    
    def file_exists_add_number(path_file_name, digits=2):
    
        pfn = pathlib.Path(path_file_name)
        parent = pfn.parent     # parent-dir of file
        stem = pfn.stem         # file-name w/o extension
        suffix = pfn.suffix     # NOTE: extension starts with '.' (dot)!
    
        try:
            # search for files ending with '-\d\d.ext'
            last_file = itz.last(parent.glob(f"{stem}-{digits * '?'}{suffix}"))
        except:
            curr_no = 1
        else:
            curr_no = int(last_file.stem[-digits:]) + 1
    
        # int to string and add leading zeros
        curr_no = str(last_no).zfill(digits)
        path_file_name = parent / f"{stem}-{curr_no}{suffix}"
    
        return str(path_file_name)
    

    Pls note: That solution starts at 01 and will only find file-pattern containing -\d\d!

    0 讨论(0)
提交回复
热议问题