首先,您确定要使用 Python 执行此操作吗?有几个功能齐全的文件重命名实用程序可以满足您的需求。 (我个人最喜欢的是 Linux 下的 KRename。)
假设您确实想在 python 中执行此操作...
Q1) 将文件名与其扩展名分开
使用os.path.splitext() 将文件名分为“名称”和“扩展名”部分。然后,您可以在不更改扩展名的情况下操作文件名,并在完成后将它们重新组合在一起。例如:
import os, pprint
filenames = [f for f in os.listdir('D:\\Freeware')]
name_and_ext_list = [os.path.splitext(f) for f in filenames]
pprint.pprint(filenames)
pprint.pprint(name_and_ext_list)
提供类似的输出
['a43.zip',
'Amphetype-0.16-win32.exe',
'aMSN-0.98.4-tcl85-windows-installer.exe',
'andlinux-beta2-minimal.exe',
'ATF-Cleaner.exe',
'aurora-setup.exe',
[('a43', '.zip'),
('Amphetype-0.16-win32', '.exe'),
('aMSN-0.98.4-tcl85-windows-installer', '.exe'),
('andlinux-beta2-minimal', '.exe'),
('ATF-Cleaner', '.exe'),
('aurora-setup', '.exe'),
请注意,os.path.splitext() 比您可能自己滚动的任何东西都更强大。它不会被文件名中的多余点弄糊涂 - 例如:
>>> os.path.splitext('Zipped Party Food Invoice 22.09.2011.xlsx.zip')
('Zipped Party Food Invoice 22.09.2011.xlsx', '.zip')
Q2) “模糊”搜索和替换
您的示例代码,将所有字符 BCDEF 替换为 A,可以使用 @kev 建议的正则表达式来完成。
编辑 2 由于您想替换整个单词,而不是特定的单个字符 B, C, D, E, F,您可以尝试以下代码。这不是特别有效(它必须为您要搜索和替换的每个单词扫描一次文件列表) - 它有效,但欢迎改进。一个好的解决方案只需要遍历字符串。
def replace_words ( input_string ):
replacement_lists = { \
"Electronics" : ["Computer", "CD Player", "Camera", "Coffee Grinder"],
"Baked Goods" : ["Cheesecake", "Muffin","Cookie"] }
output_string = input_string
for type_of_thing, list_of_things in replacement_lists.iteritems():
for thing in list_of_things:
output_string = output_string.replace(thing, type_of_thing)
return output_string
input_names = [ \
"Coffee Cup.jpg",
"Computer Disks.docx",
"Muffins.jar",
"CD Player Maintenance.lzma",
"Cookie Monster's 101 Types of Cookie.pdf" ]
output_names = [replace_words(x) for x in input_names]
输出如下:
>>> pprint.pprint(input_names)
['Coffee Cup.jpg',
'Computer Disks.docx',
'Muffins.jar',
'CD Player Maintenance.lzma',
"Cookie Monster's 101 Types of Cookie.pdf"]
>>> pprint.pprint(output_names)
['Coffee Cup.jpg',
'Electronics Disks.docx',
'Baked Goodss.jar',
'Electronics Maintenance.lzma',
"Baked Goods Monster's 101 Types of Baked Goods.pdf"]
Q3) 删除所有破折号,除非被单词字符包围
又是正则表达式的工作。试试:
>>> teststring = "Coca-Cola - A History.pdf"
>>> re.sub(r'(\W)-(\W)',r'\1\2',teststring)
'Coca-Cola A History.pdf'
这将删除任何未被“单词字符”\w 包围的破折号,松散地定义为任何字母数字字符、任何数字或下划线。 \W 匹配 非-word 字符,即任何 不 与 \w 匹配的内容。
1) \w 取决于区域设置:如果您的文件名是俄语,那么西里尔字符也将被视为“单词字符”。
注意事项:
2) 正则表达式实际上匹配三个字符 - 替换字符串中的\1 和\2 用于将两个字符放回破折号的两侧。 (参见:“反向引用”。)
3) 注意使用原始字符串 r"..." 而不是普通字符串 "..."。这是为了防止 Python 破坏正则表达式中的反斜杠。
编辑:这是一个(未经测试的)示例,说明如何将文件名与扩展名分开处理。请注意,我已将所有繁重的工作转移到一个单独的函数中,而不是使用列表推导。
列表推导式非常适合替换做一两件事的循环,但我个人发现嵌套列表推导式很难阅读。请记住,长度超过 80 个字符的行是代码异味的指标。
import os, shutil, re
def rename_file (original_filename):
name, extension = os.path.splitext(original_filename)
#remove one or more dashes, surrounded by non-word characters.
modified_name = re.sub(r"(\W)-+(\W)",r"\1\2",name)
new_filename = modified_name + extension
try:
# moves files or directories (recursively)
shutil.move(original_filename, new_filename)
except shutil.Error:
print ("Couldn't rename file %(original_filename)s!" % locals())
target_dir = r"/home/trinity/nmap"
targets = os.listdir(target_dir)
[rename_file(f) for f in targets]