Reputation: 4996
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
This works, but if I run it on a directory which I have already run it on, it seems to delete half of the files its renaming. Why would this happen?
Upvotes: 3
Views: 102
Reputation: 94871
It's easier to see what's happening if you print out the renaming you're doing:
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 sample output running 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 here's the test directory contents:
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
and b.cropped0.txt
have disappeared. The output above reveals 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 two files to the missing names, and then rename them again later, which means we lose whatever was in b.cropped4.txt
and b.cropped5.txt
.
You can avoid this by making sure the new name you're going to use doesn't already exist, and if it does, increment count
until you get a file that doesn't 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
Upvotes: 3
Reputation: 14685
It would happen when a file with the new name already exists, so you are replacing an existing file with a renamed one, losing the original in the process.
Upvotes: 0