【问题标题】:Python: simple batch rename files in windows folderPython:Windows文件夹中的简单批量重命名文件
【发布时间】:2016-05-08 13:06:36
【问题描述】:

尝试创建一个简单的代码,在windows中批量重命名一个文件夹。

必须:

  • 改变每个数字,比如“file02.txt”,把02变成0002

  • 可能适用于每种文件格式,如 jpg、png、txt、docx 等(因为我不确定文件夹中的内容,此代码可能用于图像序列...)

这可能吗?

我做了测试版本,结合了我所拥有的小知识,但这让我感到困惑。

到目前为止我的代码:

import os
import sys


folder_path = os.listdir(raw_input("Insert folder path: "))
print "Files in folder: %s" % folder_path

# a split tool
def mysplit(s):
    head = s.rstrip('0123456789')
    tail = s[len(head):]
    return head, tail

# a function to make a new name with needed 0000
def new_filename(filename):
    file_name_part, ext = os.path.splitext(filename) #  file01 and .ext

    original_name, number = mysplit(file_name_part) # 01 and file
    add_zero = number.rjust(4, "0") # add 0001

new_name = original_name + add_zero + ext

print new_name
    # new_name  comes like this ['file0001.txt'] but seperate, not in a list? Why?



for current_file_n in folder_path:
    new = new_filename(current_file_n)
    print list([new]) # trying to make the str into a list....


re_name = os.renames(current_file_n, new)
print re_name
print "Renamed files: %s" % folder_path

期望的结果与开始列表相同,但用零排序,例如:['file0001.txt', 'file0002.txt', 'file0003.txt'......'file0015.txt ']

我遇到了诸如 windows error: can't find file 和另一个错误之类的错误;无法连接str和list?

我需要尽可能简单地解释我做错了什么,或者我可以使用另一种方法来达到我想要的结果?

【问题讨论】:

  • 看起来不对的一件事是您的new_filename() 函数没有显式返回任何内容,因此有效地返回None 并且您在它之后的缩进是混乱的。无论直接或间接使用其返回值,这都会导致进一步的错误。
  • 您的缩进似乎搞砸了,因为您在代码中混合使用了制表符和空格。最好只使用空格(或将编辑器配置为自动用它们替换制表符)。
  • @martineau 谢谢,我没有意识到空格和制表符可能是个问题

标签: python windows rename


【解决方案1】:

正如 martineau 所说,你的缩进搞砸了。

这是工作代码:

import os
import sys

# a split tool
def mysplit(s):
    head = s.rstrip('0123456789')
    tail = s[len(head):]
    return head, tail

# a function to make a new name with needed 0000
def new_filename(filename):
    file_name_part, ext = os.path.splitext(filename) #  file01 and .ext

    original_name, number = mysplit(file_name_part) # 01 and file
    add_zero = number.rjust(4, "0") # add 0001

    new_name = original_name + add_zero + ext

    return new_name
    # new_name  comes like this ['file0001.txt'] but seperate, not in a list? Why?

if __name__ == '__main__':
     folder_path = os.listdir(raw_input("Insert folder path: "))
     print "Files in folder: %s" % folder_path
     renamed_files = [] 
     for current_file_n in folder_path:
          new = new_filename(current_file_n)
          renamed_files.append(new) # Add renamed file's name to a list
          try:
               os.renames(current_file_n, new) #It doesn't return anything
               print new
          except:
               print "Unexpected error while renaming %s:%s"%(new, sys.exc_info()[0])
     print "Renamed files: %s" % renamed_files

希望对你有帮助

【讨论】:

  • @Chrisy:您需要更精确,并指定确切的错误和显示的任何错误消息。
  • @martineau 是的,它的错误不大,但错误消息:“重命名 im0004.jpg 时出现意外错误:” 在所有文件的一行中,然后它没有被重命名...
  • @Chrisy:啊……我怀疑这个错误是因为脚本没有检查新文件名是否与文件已有的文件名相同——你可能不能将文件重命名为已有的名称。
  • @martineau 但“file0001.txt”与原来的“file01.txt”不一样吗?或者当只有其中一个具有相同的名称时,它会停止整体重命名吗?
  • @Chrisy:是的,但您说错误消息是“在重命名 im0004.jpg 时”。您可以通过不尝试重命名文件 if current_file_n == new: 来轻松测试我的理论,无论它是否是错误的原因(因为即使允许,这也是浪费时间)。另一种可能性是两个不同的文件名在扩展后都将变得相同。即“file1.txt”和“file01.txt”都变成“file0001.txt”。显然它们不能都重命名为相同的东西。
【解决方案2】:

使用正则表达式替换可以大大简化您的代码。 re.sub() 可以带替换功能。在这种情况下,将前导零添加到文件名中找到的第一个数字。

import os, re

def renumber_files(directory, zeroes=4):
    os.chdir(directory)
    for filename in os.listdir(directory):
        new_name = re.sub(r'\d+', lambda m: m.group().zfill(zeroes), filename, count=1)
        os.rename(filename, new_name)


renumber_files(raw_input("Insert folder path: "))

这是可行的,因为 re.sub() 可以将可调用对象作为替换参数。

Signature: re.sub(pattern, repl, string, count=0, flags=0) 

返回替换最左边不重叠得到的字符串 替换 repl 在字符串中出现的模式。重复 可以是字符串或可调用对象;如果是字符串,则反斜杠转义 在其中进行处理。如果它是可调用的,则通过匹配 对象,并且必须返回要使用的替换字符串。

在 lambda m.group() 中返回一个匹配模式 \d+ 的字符串。例如“1”、“564645”或“005”。

下一步,str.zfill(4),将它们变成“0001”、“564645”或“0005”。

【讨论】:

  • 您应该知道这可能会覆盖文件。例如:如果你有image1.jpgimage01.jpgimage0001.jpg三个文件,运行函数后只剩下一个。您可以检查这是否即将发生,并可能在您做之前中止或要求确认os.rename(filename, new_name)
  • Chrisy 正在使用 Windows,如果目标名称已经存在,os.rename 会引发 OSError。这不一定会改变您的建议,但上下文不同。考虑到竞争线程和进程的竞争条件,无论如何您都必须处理异常。
  • @HåkenLid 谢谢!效果很好!你能解释一下 re.sub() 中的步骤是如何工作的吗?
  • 当然。我添加了一个简短的解释。
猜你喜欢
  • 2015-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-22
  • 2012-05-04
  • 2021-11-07
  • 2016-07-04
相关资源
最近更新 更多