Python入门教程-05 休闲一刻 文件重命名示例
2014-04-19 16:18
519 查看
本文属于利用Python解决日常小问题的一个例子。
而每个级别下又包括多个故事:
每个故事的音频文件是01.mp3,02.mp3等:
如果把所有这些音频文件导入到iTune或Android手机的音频播放器中,则会出现多个诸如01.mp3文件,而无法得知每个01.mp3对应的具体的故事名称,所以在选曲的时候会非常不方便。
为此,希望把故事名称添加到01.mp3等文件名的前面,即如下的效果:
如果觉得文件名太长,可以把故事名称最前面的01、02等字样去掉。
为此,要寻求一种自动修改的方法,——毕竟这个重命名是有规律可循。
这里以Python级别为例来实现这个目的。
为此,分为如下几个迭代:
遍历指定顶层目录下面的各个最底层的目录;
获取该最底层目录下的文件列表;
如果文件名是01.mp3样式的名称,则需要重命名;
否则,则说明已经手工修改过了,直接跳过即可;
重命名时,
首先获取最底层目录的名称;
依次构造每个mp3文件的目标文件名;
重命名文件;
接下来按照上述步骤,逐步丰富Python脚本。
指定一个目录,返回这个目录下面的所有最底层目录。
和链接不同的是,这里仅仅获取目录,而不包括文件。——这样的话,就可以按照前面设计的思路一步步往下走。但是否一定要这样处理呢?
软件开发中,一个非常流行的词汇就是“变化”。就这里来讲,我们的设计也需要变化。更恰当地讲,我们这里还称不上“设计”,称谓“算法”可能更为合适。毕竟是一个小程序。
当外部可用资源发生变化的时候,及时调整已有的算法。
举个例子,假如我们已经有个库函数,可以返回指定目录下的所有最底层目录。那么我们使用最开始的算法就是合适的。
至此,Sprint1的结论是:调整设计,更新迭代计划。——Sprint 1更像一个Technical Sprint!
这里的调整主要是把原计划的第一步和第二步合并一起。
运行结果如下:
这个是编码的问题,因为第24行用到了中文。为此,代码修改如下(添加了第一行):
运行结果:
目前的代码是打印了目录和文件,所以需要进一步把目录过滤掉(添加了if语句):
运行结果:
大家可能会注意到脚本文件rename.py也在输出之列。这个倒无关紧要,因为我们后面的算法只需要处理01.mp3之类的文件,会自动过滤掉其他文件。
至此,我们达到了sprint2的目标,即可以遍历指定目录下的所有mp3文件了。接下来就是重命名。
注意到,我们已经对代码进行了重构,把对文件和目录的判别放到need_rename()函数中。接下来就是丰富上面两个桩函数。
通常来讲,对于每个函数,都需要单独编码、单独测试。但对我们这个小例子来讲,全部略过,即砍掉了UT,直接IT&ST了。进一步地,也没有做Automation Test,而全部Manual Test。
最后的代码:
运行效果:
可以看到总共50行不到的代码,即实现了大量文件的重命名,从而把自己从枯燥无味的工作中解脱出来。
作为小练习、小程序,这种重复、性能问题是可以容忍的。但通常在开发正式的程序时,对这种bad smell代码还是需要及时优化。
1. 问题描述
书虫系列是非常优秀的英语学习读物,这个系列包括多个级别,如入门级1、入门级2、第三级,等等:而每个级别下又包括多个故事:
每个故事的音频文件是01.mp3,02.mp3等:
如果把所有这些音频文件导入到iTune或Android手机的音频播放器中,则会出现多个诸如01.mp3文件,而无法得知每个01.mp3对应的具体的故事名称,所以在选曲的时候会非常不方便。
为此,希望把故事名称添加到01.mp3等文件名的前面,即如下的效果:
如果觉得文件名太长,可以把故事名称最前面的01、02等字样去掉。
2. 低效的方法
当然一种最直接的方法就是手工去重命名每个mp3文件。但因为有大量的文件,这个重命名的活就变得很枯燥,且效率低下。为此,要寻求一种自动修改的方法,——毕竟这个重命名是有规律可循。
这里以Python级别为例来实现这个目的。
3. 解决方案
3.1 总体思路
可以遍历指定目录下面的各个文件夹,如果该文件夹下面是01.mp3之类的文件,就表示该目录下的文件需要重命名。重命名的方法是首先取出该目录的名称,然后添加到目录下面的每个文件名的前面。为此,分为如下几个迭代:
遍历指定顶层目录下面的各个最底层的目录;
获取该最底层目录下的文件列表;
如果文件名是01.mp3样式的名称,则需要重命名;
否则,则说明已经手工修改过了,直接跳过即可;
重命名时,
首先获取最底层目录的名称;
依次构造每个mp3文件的目标文件名;
重命名文件;
接下来按照上述步骤,逐步丰富Python脚本。
Sprint1:遍历所有目录
在“Python语言获取目录下所有文件或目录的方法”一文中,给出了递归遍历某目录下所有子目录和文件的函数。基于这个函数,我们可以类似地设计这样的一个函数:指定一个目录,返回这个目录下面的所有最底层目录。
和链接不同的是,这里仅仅获取目录,而不包括文件。——这样的话,就可以按照前面设计的思路一步步往下走。但是否一定要这样处理呢?
软件开发中,一个非常流行的词汇就是“变化”。就这里来讲,我们的设计也需要变化。更恰当地讲,我们这里还称不上“设计”,称谓“算法”可能更为合适。毕竟是一个小程序。
当外部可用资源发生变化的时候,及时调整已有的算法。
举个例子,假如我们已经有个库函数,可以返回指定目录下的所有最底层目录。那么我们使用最开始的算法就是合适的。
至此,Sprint1的结论是:调整设计,更新迭代计划。——Sprint 1更像一个Technical Sprint!
这里的调整主要是把原计划的第一步和第二步合并一起。
Sprint2:遍历所有的mp3文件
我们直接重用“Python语言获取目录下所有文件或目录的方法”,得到如下的代码:# Findthe every dir, if 01.rm exist in it, then rename it. #!/usr/bin/python ''' Utilitiesof file & directories. ''' import os # Get theall files & directories in the specified directory (path). defget_recursive_file_list(path): current_files = os.listdir(path) all_files = [] for file_name in current_files: full_file_name = os.path.join(path,file_name) all_files.append(full_file_name) if os.path.isdir(full_file_name): next_level_files =get_recursive_file_list(full_file_name) all_files.extend(next_level_files) return all_files top_dir ="C:\\English\\书虫" all_files= get_recursive_file_list(top_dir) printall_files
运行结果如下:
C:\English\书虫>python rename.py File "rename.py", line 24 SyntaxError:Non-ASCII character '\xca' in file rename.py on line 24, but no enc odingdeclared; see http://www.python.org/peps/pep-0263.html for details
这个是编码的问题,因为第24行用到了中文。为此,代码修改如下(添加了第一行):
#coding=gbk # Findthe every dir, if 01.rm exist in it, then rename it. #!/usr/bin/python ''' Utilitiesof file & directories. ''' import os # Get theall files & directories in the specified directory (path). defget_recursive_file_list(path): current_files = os.listdir(path) all_files = [] for file_name in current_files: full_file_name = os.path.join(path,file_name) all_files.append(full_file_name) if os.path.isdir(full_file_name): next_level_files =get_recursive_file_list(full_file_name) all_files.extend(next_level_files) return all_files top_dir ="C:\\English\\书虫" all_files= get_recursive_file_list(top_dir) for filein all_files: print file.decode("gbk")
运行结果:
目前的代码是打印了目录和文件,所以需要进一步把目录过滤掉(添加了if语句):
top_dir = "C:\\English\\书虫" all_files = get_recursive_file_list(top_dir) for file in all_files: if os.path.isfile(file): print file.decode("gbk")
运行结果:
大家可能会注意到脚本文件rename.py也在输出之列。这个倒无关紧要,因为我们后面的算法只需要处理01.mp3之类的文件,会自动过滤掉其他文件。
至此,我们达到了sprint2的目标,即可以遍历指定目录下的所有mp3文件了。接下来就是重命名。
Sprint3:重命名mp3文件
有了文件名,重命名相对简单一些。为此,确定如下的伪代码:def need_rename(filename): return True def rename(filename): old_filename = filename new_filename = filename # to be done #rename it top_dir = "C:\\English\\书虫" all_files = get_recursive_file_list(top_dir) for file in all_files: if not need_rename(file): continue rename(file) print file.decode("gbk")
注意到,我们已经对代码进行了重构,把对文件和目录的判别放到need_rename()函数中。接下来就是丰富上面两个桩函数。
通常来讲,对于每个函数,都需要单独编码、单独测试。但对我们这个小例子来讲,全部略过,即砍掉了UT,直接IT&ST了。进一步地,也没有做Automation Test,而全部Manual Test。
最后的代码:
def need_rename(filename): if not os.path.isfile(filename): return False base_filename = os.path.basename(filename) pattern = re.compile("^[\d]{2}.mp3$") if pattern.match(base_filename): print base_filename return True else: return False def rename(filename): old_filename = filename base_filename = os.path.basename(filename) dir_name = os.path.dirname(filename) #print "%s ----------- %s" % (dir_name, base_filename) story_name = os.path.basename(dir_name) #print "story name: ", story_name new_filename = os.path.join(dir_name, story_name[3:] + " " + base_filename) os.rename(old_filename, new_filename) print "%s ==> %s" % (old_filename, new_filename) top_dir = "C:\\English\\书虫" all_files = get_recursive_file_list(top_dir) for file in all_files: if not need_rename(file): continue rename(file)
运行效果:
可以看到总共50行不到的代码,即实现了大量文件的重命名,从而把自己从枯燥无味的工作中解脱出来。
4. 后记
可以看到need_rename和rename两个函数存在一定的代码重复,而且一些重复操作也降低了代码运行效率。作为小练习、小程序,这种重复、性能问题是可以容忍的。但通常在开发正式的程序时,对这种bad smell代码还是需要及时优化。
相关文章推荐
- 006_004 Python 链式遍历字典
- python程序在DOS界面下的执行过程
- Python 之 使用 PIL 库做图像处理
- 【Python排序搜索基本算法】之拓扑排序
- Python mysqlDB 掉线自动连接 返回插入字典
- python 学习日志(2)
- win7环境中使用notepad++配置python IDE
- PTVS (Python Tools for Visual Studio)
- python常用函数
- 23种设计模式之python实现--Memento模式
- Python PIL模块整理
- Python字符串的编码与解码(encode与decode)
- python函数参数学习笔记
- python json
- python不是内部命令或外部命令,也不是可执行程序解决方案
- Implementing a Principal Component Analysis (PCA) in Python step by step
- python几种安装插件方法的比较
- Python单元测试——深入理解unittest
- django使用python manage.py syncdb注意事项
- Python 代码调试技巧使用 PyDev 进行调试