Renaming Python files is weird

I have this function:

def rename(path):
    """ Renames all the files to be cropped-%d.xxx """
    count = 0
    for thing in os.listdir(path):
        root, ext = os.path.splitext(thing)
        os.rename(os.path.join(path, thing), os.path.join(path, sys.argv[1]+".cropped{0}".format(count)+ext))
        count += 1

      

It works, but if I run it in the directory where I already ran it, it seems to delete half of the files, rename. Why is this happening?

+3


source to share


2 answers


It's easier to see what happens if you print out the rename you do:

def rename(path):
    """ Renames all the files to be cropped-%d.xxx """
    count = 0 
    for thing in os.listdir(path):
        root, ext = os.path.splitext(thing)
        old = os.path.join(path, thing)
        new = os.path.join(path, sys.argv[1] + ".cropped{0}".format(count) + ext)
        print("rename from {} to {}".format(old, new))
        os.rename(old, new)
        count += 1

      

Here's the test output being run twice:

dan@dandesk:~$ python ok.py b
rename from test/4.txt to test/b.cropped0.txt
rename from test/2.txt to test/b.cropped1.txt
rename from test/5.txt to test/b.cropped2.txt
rename from test/7.txt to test/b.cropped3.txt
rename from test/1.txt to test/b.cropped4.txt
rename from test/3.txt to test/b.cropped5.txt
rename from test/6.txt to test/b.cropped6.txt
dan@dandesk:~$ python ok.py b
rename from test/b.cropped3.txt to test/b.cropped0.txt
rename from test/b.cropped4.txt to test/b.cropped1.txt
rename from test/b.cropped2.txt to test/b.cropped2.txt
rename from test/b.cropped5.txt to test/b.cropped3.txt
rename from test/b.cropped1.txt to test/b.cropped4.txt
rename from test/b.cropped0.txt to test/b.cropped5.txt
rename from test/b.cropped6.txt to test/b.cropped6.txt

      

And now the contents of the test directory:

dan@dandesk:~$ ls -1 test
b.cropped2.txt
b.cropped3.txt
b.cropped4.txt
b.cropped5.txt
b.cropped6.txt

      

As you can see, b.cropped1.txt

they b.cropped0.txt

disappeared. The above result shows why:



rename from test/b.cropped3.txt to test/b.cropped0.txt
rename from test/b.cropped4.txt to test/b.cropped1.txt
...
rename from test/b.cropped1.txt to test/b.cropped4.txt
rename from test/b.cropped0.txt to test/b.cropped5.txt

      

We rename the two files to missing names and then rename them later, which means we lose everything in b.cropped4.txt

and b.cropped5.txt

.

You can avoid this by making sure that the new name you intend to use does not already exist, and if so, increase count

it until you get a file that does not exist:

def rename(path):
    """ Renames all the files to be cropped-%d.xxx """
    count = 0
    for thing in os.listdir(path):
        root, ext = os.path.splitext(thing)
        old = os.path.join(path, thing)
        while True:
            new = os.path.join(path, sys.argv[1] + ".cropped{0}".format(count) + ext)
            if not os.path.exists(new):
                break
            count += 1
        print("rename from {} to {}".format(old, new))
        os.rename(old, new)
        count += 1

      

Output:

dan@dandesk:~$ python ok.py b
rename from test/4.txt to test/b.cropped0.txt
rename from test/2.txt to test/b.cropped1.txt
rename from test/5.txt to test/b.cropped2.txt
rename from test/1.txt to test/b.cropped3.txt
rename from test/3.txt to test/b.cropped4.txt
rename from test/6.txt to test/b.cropped5.txt
dan@dandesk:~$ python ok.py b
rename from test/b.cropped3.txt to test/b.cropped6.txt
rename from test/b.cropped4.txt to test/b.cropped7.txt
rename from test/b.cropped2.txt to test/b.cropped8.txt
rename from test/b.cropped5.txt to test/b.cropped9.txt
rename from test/b.cropped1.txt to test/b.cropped10.txt
rename from test/b.cropped0.txt to test/b.cropped11.txt

      

+3


source


This will happen when a file with the new name already exists, so you replace the existing file with the renamed one, losing the original in the process.



0


source







All Articles