kevin ver
kevin ver

Reputation: 851

Renaming multiple files

So i'm trying to rename a list of files with set renames like so:

import os
import time
for fileName in os.listdir("."):
    os.rename(fileName, fileName.replace("0001", "00016.5"))
    os.rename(fileName, fileName.replace("0002", "00041"))
    os.rename(fileName, fileName.replace("0003", "00042"))
...

but that gives me this error os.rename(fileName, fileName.replace("0002", "00041"))``OSError: [Errno 2] No such file ordirectory (the file is in the directory)

So next i tried

import os
import time
for fileName in os.listdir("."):
    os.rename(fileName, fileName.replace("0001", "00016.5"))
for fileName in os.listdir("."):
    os.rename(fileName, fileName.replace("0002", "00041"))
for fileName in os.listdir("."):
    os.rename(fileName, fileName.replace("0003", "00042"))
...

But that renames the files very strangely with a lot on extra characters, what im i doing wrong here?

Upvotes: 0

Views: 75

Answers (2)

Maurice Meyer
Maurice Meyer

Reputation: 18136

listdir returns all object's names (files, directories, ...) not a full path. You can construct a full path using: os.path.join(). Your for loop renames, all found objects first to 00016.5, then to 00041 ...

One way to rename the files, could the following:

import os
import time

currentDir = os.pathdirname(__file__)
for fileName in os.listdir(currentDir):
    if '0001' in fileName:
        oldPath = os.path.join(currentDir, fileName)
        newPath = os.path.join(currentDir, fileName.replace("0001", "00016.5"))
    elif '0002' in fileName:
        oldPath = os.path.join(currentDir, fileName)
        newPath = os.path.join(currentDir, fileName.replace("0002", "00041"))
    else:
        continue

    os.rename(oldPath, newPath)

Upvotes: 1

Jean-François Fabre
Jean-François Fabre

Reputation: 140286

The fact that multi-pass renaming works while single pass renaming doesn't means that some of your files contain the 0001 pattern as well as 0002 pattern.

So when doing only one loop, you're renaming files but you're given the old list of files (listdir returns a list, so it's outdated as soon as you rename a file) => some source files cannot be found.

When doing in multi-pass, you're applying multiple renames on some files.

That could work (and is more compact):

for fileName in os.listdir("."):
    for before,after in (("0001", "00016.5"),("0002", "00041"),("0003", "00042")):
        if os.path.exists(fileName):
            newName = fileName.replace(before,after)
            # file hasn't been renamed: rename it (only if different)
            if newName != fileName:
                os.rename(fileName,newName)

basically I won't rename a file if it doesn't exist (which means it has been renamed in a previous iteration). So there's only one renaming possible. You just have to prioritize which one.

Upvotes: 1

Related Questions