2

Let's say:

  • I'd like to rename a file original.txt as name.txt.
  • If name.txt exists, rename as name(0).txt.
  • If name(0).txt exists, rename as name(1).txt, and so on.
  • I don't want to delete nor overwrite the same name files.

I came up the code that achieves this, but utterly verbose.

import os

try:
    os.rename("original.txt", "name.txt")
except FileExistsError:
    i = 0
    while True:
        try:
            os.rename("original.txt", f"name({i}).txt")
            break
        except:
            if i >= 9:
                raise Exception("Too many same name files")
            i += 1
except:
    print("Unexpected error")

Is there a more suitable function or concise way to do this?

By the way, this post is related, however, the all answers assume the same name files can be deleted, which is not true in my case.

Edit: To be clear, I think it's appopriate to add the following requirements.

  • It should be checked whether the file is successfully created after operation.
  • Any errors should be catched by except.
catwith
  • 875
  • 10
  • 13
  • You can get the list of files in the directory using `os.walk` and check which filename is available – drum Jan 16 '21 at 05:34
  • 1
    That's pretty much how I would do it. It's concise enough imo, and you might risk sacrificing readability if you try shortening it. The only change I think you should make is have both excepts as `except FileExistsError`. You don't want to catch any other exceptions. – Armadillan Jan 16 '21 at 05:34
  • `os.listdir` is probably better here than `os.walk` imo, since you are confined to one directory anyway. – Armadillan Jan 16 '21 at 05:36
  • 1
    Since this is working code you want to improve, I think this is best suited for https://codereview.stackexchange.com/ – costaparas Jan 16 '21 at 05:39
  • 1
    It is not a good idea to switch to a scan and write approach as suggested in some of these comments because you can introduce a race condition should any other process be writing files in the same location. – dpwr Jan 16 '21 at 08:27

1 Answers1

0

You Can try using a for loop like this:

import os

original_filename = 'original.txt'

for number in range(0, 10000, 1):
    try:
        #Cheking whether the file exists
        #If the file exists, then it will raise FileExistsError
        #Else create a file
        try_to_create_a_file = open(f'name{number}.txt', 'x')

        #If the file is created by the above code, then delete the file
        os.remove('name{number}.txt')

        #Then rename the file
        os.rename(original_filename, f'name{number}.txt')

       #Then break the for loop
       break
    except FileExistsError:
       #Continue the for loop if the file exists
       continue
Dharman
  • 30,962
  • 25
  • 85
  • 135
Parvat . R
  • 751
  • 4
  • 21
  • If any errors, please reply! – Parvat . R Jan 16 '21 at 05:47
  • 1
    This approach is obscure -- use `os.path.exists`... – costaparas Jan 16 '21 at 05:48
  • 1
    Technically, this also doesn't cover the base case of renaming to `name.txt` (without a number) – costaparas Jan 16 '21 at 05:49
  • Thanks for the code. Wouldn't it be longer than the code in my question post if you need to raise an error if the file counldn't be created after the loop? – catwith Jan 16 '21 at 07:55
  • Which error are you saying about? And its not longer than your code, try removing the comments and extra lines. I just expanded that so, you can read that clearly. – Parvat . R Jan 16 '21 at 09:26
  • I was taking about when you have to raise an error if the file could not be created even if the whole loop ends. But maybe it's not neccessary to check it. Thank you. – catwith Jan 17 '21 at 03:08