Python重命名文件的行为很奇怪

3

我有这个函数:

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

这段代码有效,但如果我在已经运行它的目录上再次运行它,它似乎会删除一半要重命名的文件。为什么会这样?

1
在你的代码中,你会采取哪些预防措施以确保目录中不存在与你要重命名的文件同名的文件? - 5gon12eder
1
也许您正在重命名现有文件之上。(这不是错误;旧文件将被删除。) - nneonneo
啊,是的,那就是了。现在如何进行一个简洁的检查呢?我可以用if语句来检查名称是否存在吧。 - chris
2个回答

3

如果您打印出正在进行的重命名操作,那么就更容易看到发生了什么:

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

以下是运行两次的示例输出:
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

现在,这里是测试目录的内容:

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

正如您所见,b.cropped1.txtb.cropped0.txt已经消失。上面的输出显示了原因:

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

我们将两个文件重命名为缺失的名称,然后稍后再次重命名它们,这意味着我们会丢失b.cropped4.txtb.cropped5.txt中的任何内容。
您可以通过确保要使用的新名称不存在来避免这种情况,如果存在,则递增计数器count,直到找到一个不存在的文件为止:
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

输出:

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

即使它基本上是在我说完之后才说的,但对于非常彻底的答案,我还是要点个赞 ;) - GreenAsJade

0

这种情况通常发生在已经存在一个同名文件的情况下,因此您正在用重命名后的文件替换现有文件,从而丢失了原始文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接