burglarhobbit
burglarhobbit

Reputation: 2291

WindowsError: [Error 2] The system cannot find the file specified, cannot resolve in Python

I have made a Python program which will clean up the unnecessary names present in my downloaded torrent files+folders, so that I can upload it to my unlimited Google Drive Storage Account without much hassle.

However, it gives me the: WindowsError: [Error 2] The system cannot find the file specified after certain number of iterations.If I run the program again, it works fine for a certain iterations and then the same error pops up.

Note that I have taken precautions using os.path.join to avoid this error but it keeps coming up. Because of this error, I have to run the program tens of times over a selected folder/drive.

Here is my program:

import os
terms = ("-LOL[ettv]" #Other terms removed
)
#print terms[0]
p = "E:\TV Series"
for (path,dir,files) in os.walk(p):
    for name in terms:
        for i in files:
            if name in i:
                print i
                fn,_,sn = i.rpartition(name)
                os.rename(os.path.join(path, i), os.path.join(path, fn+sn))
        for i in dir:
            if name in i:
                print i
                fn,_,sn = i.rpartition(name)
                os.rename(os.path.join(path, i), os.path.join(path, fn+sn))

And the Error Traceback:

Traceback (most recent call last):
File "E:\abcd.py", line 22, in <module>
os.rename(os.path.join(path, i), os.path.join(path, fn+sn))
WindowsError: [Error 2] The system cannot find the file specified

Upvotes: 3

Views: 1670

Answers (1)

Nikita
Nikita

Reputation: 6341

Probably it's the problem with subdirectories due to the way os.walk works, namely path on next iteration after the first with subdirectories. os.walk gathers subdirectories' names to visit on further iterations on it's first iteration in current directory...

E.g., on first call to os.walk you get:

('.', ['dir1', 'dir2'], ['file1', 'file2'])

now you rename the files (this works ok), and you rename: 'dir1' to 'dirA' and 'dir2' to 'dirB'.

On next iteration of os.walk, you get:

('dir1', ['subdir1-2', 'subdir1-2'], ['file1-1', 'file1-2'])

And what happens here is there's no 'dir1' anymore, as it is already renamed on the file system, but os.walk still remembers it's old name in the list inside and gives it to you. Now, when you try to rename 'file1-1' you ask for 'dir1/file1-1', but on the file system it's actually is 'dirA/file1-1' and you get the error.

To solve this issue, you need to change the values in the list that is used by os.walk on further iterations, e.g. in your code:

for (path, dir, files) in os.walk(p):
    for name in terms:
        for i in files:
            if name in i:
                print i
                fn, _, sn = i.rpartition(name)
                os.rename(os.path.join(path, i), os.path.join(path, fn+sn))
        for i in dir:
            if name in i:
                print i
                fn, _, sn = i.rpartition(name)
                os.rename(os.path.join(path, i), os.path.join(path, fn+sn))
                #here remove the old name and put a new name in the list
                #this will break the order of subdirs, but it doesn't
                #break the general algorithm, though if you need to keep
                #the order use '.index()' and '.insert()'.
                dirs.remove(i)
                dirs.append(fn+sn)

This should do the trick and in described above scenario, will lead to...

On first call to os.walk:

('.', ['dir1', 'dir2'], ['file1', 'file2'])

now rename: 'dir1' to 'dirA' and 'dir2' to 'dirB' and change the list as shown above... Now, on next iteration of os.walk it should be:

('dirA', ['subdir1-2', 'subdir1-2'], ['file1-1', 'file1-2'])

Upvotes: 3

Related Questions