@zhangyu756897669
2017-09-17T15:28:09.000000Z
字数 2972
阅读 569
python官方文档
假如你的老板在名字中给你发送数以千计的美式日期文件(MM-DD-YYYY),并将它们重命名为欧式日期(DD-MM-YYYY)。这个无聊的任务可能需要一整天的时间来完成!我们来写一个程序来代替。
程序的功能如下:
这意味着代码将需要执行以下操作:
对于该项目,打开一个新的文件编辑器窗口,并将您的代码保存为renameDates.py。
该程序的第一部分将需要导入必要的模块并创建一个可以识别MM-DD-YYYY日期的正则表达式。。将它们作为TODO键入,可以方便地使用IDLE的CTRL-F查找功能进行查找。使您的代码如下所示:
import shutil, os, re
datePattern = re.compile(r"""^(.*?) # 所有文字之前的日期
((0|1)?\d)- # 一或两位月份数字
((0|1|2|3)?\d)- # 一或两位天数数字
((19|20)\d\d) #一年的四位数字
(.*?)$ # 所有文字后的日期
""", re.VERBOSE)
#循环工作目录中的文件。
# 跳过没有日期的文件。
#获取文件名的不同部分。
# 形成欧式文件名。
# 获取完整的绝对文件路径。
#重命名文件。
从本章你可以知道shutil.move()函数可以用来重命名文件:它的参数是要重命名的文件的名称和新的文件名。由于此函数存在于shutil模块中,因此必须导入该模块
但在重命名文件之前,您需要确定要重命名的文件。具有日期的文件名,如垃圾邮件4-4-1984.txt和01-03-2014eggs.zip应该被重命名,而没有日期的文件名如littlebrother.epub可以忽略。
您可以使用正则表达式来识别此模式。在顶部导入re模块后,调用re.compile()来创建一个Regex对象.第二个参数re.VERBOSE允许正则表达式字符串中的空格和注释使其更易于阅读。
正则表达式字符串以^(。*?)开头,以匹配可能在日期之前的文件名开头的任何文本。 ((0 | 1)?\ d)组匹配月份。第一个数字可以是0或1,所以正则表达式十二月份为12,二月为02。这个数字也是可选的,所以月份可能是4月4日或4日。当天的组是((0 | 1 | 2 | 3)?\ d)并遵循类似的逻辑; 3,03和31都是天数的有效号码。 (是的,这个正则表达式会接受一些无效的日期,如4-31-2014,2-29-2013和0-15-2014。日期有很多棘手的特殊情况,很容易错过,但为了简单起见,该程序中的正则表达式工作得很好。)
1885年是有效的一年,您可以在二十或二十一世纪寻找多年。这将使您的程序不会意外地匹配非日期文件名与日期格式,如10-10-1000.txt。
(。*?)$部分正则表达式将匹配日期之后的任何文本。
接下来,程序将必须循环从os.listdir()返回的文件名字符串列表,并将它们与正则表达式匹配。应该跳过任何没有日期的文件。对于具有日期的文件名,匹配的文本将存储在几个变量中。使用以下代码填写程序中的前三个TO步骤:
for amerFilename in os.listdir('.'):
mo = datePattern.search(amerFilename)
# Skip files without a date.
if mo == None: #❶
continue #❷
# ❸ Get the different parts of the filename.
beforePart = mo.group(1)
monthPart = mo.group(2)
dayPart = mo.group(4)
yearPart = mo.group(6)
afterPart = mo.group(8)
如果从search()方法返回的Match对象为None❶,则amerFilename中的文件名与正则表达式不匹配。 continue语句❷将跳过循环的其余部分,并转到下一个文件名。
否则,正则表达式组中匹配的各种字符串存储在名为beforePart,monthPart,dayPart,yearPart和afterPart❸的变量中。这些变量中的字符串将用于在下一步中形成欧式文件名。
为了保持组号的正确性,请尝试从头开始读取正则表达式,并在每次遇到开头圆括号时计数。不用考虑代码,只需写一个正则表达式的大纲。这可以帮助您可视化组。例如:
datePattern = re.compile(r"""^(1) # all text before the date
(2 (3) )- # one or two digits for the month
(4 (5) )- # one or two digits for the day
(6 (7) ) # four digits for the year
(8)$ # all text after the date
""", re.VERBOSE)
这里,数字1到8表示您编写的正则表达式中的组。使用正则表达式的轮廓,只需括号和组号,可以让您更清楚地了解正则表达式,然后再继续执行程序的其余部分。
作为最后一步,将上一步中创建的变量中的字符串与欧式日期连接:日期在月之前。在您的程序中填写三个剩余的TODO,代码如下:
#形成欧式文件名。
euroFilename = beforePart + dayPart + '-' + monthPart + '-' + yearPart + afterPart #❶
#获取完整的绝对文件路径。
absWorkingDir = os.path.abspath('.')
amerFilename = os.path.join(absWorkingDir, amerFilename)
euroFilename = os.path.join(absWorkingDir, euroFilename)
# 重命名文件。
print('Renaming "%s" to "%s"...' % (amerFilename, euroFilename)) # ❷
#shutil.move(amerFilename, euroFilename) # 测试后取消注释 #❸
将连接的字符串存储在名为euroFilename❶的变量中。然后,将原始文件名以amerFilename和新的euroFilename变量传递给shutil.move()函数,以重命名文件❸。
该程序已将shutil.move()调用注释掉,而是打印将重命名为❷的文件名。首先运行这样的程序可以让您仔细检查文件是否正确重命名。然后,您可以取消注释shutil.move()调用并再次运行该程序以实际重命名文件。
还有很多其他原因可能需要重命名大量的文件。