根据一组规则重命名文件

时间:2012-03-06 02:32:35

标签: python

我正在使用(或尝试使用)python脚本(目前)删除和更改文件名

我希望在一个脚本中有一堆重命名功能。

Q1

我想知道怎么做,所以做文件重命名(比如删除'。'而不必在最后为fileextention重新添加它。

Q2

我还希望能够创建一个列表,这样我就可以将多个内容重命名为相同的名称,而不必为每个名称添加一行: 现在它将是:

[os.rename(f, f.replace('B', 'A')) for f in os.listdir('.') if not f.startswith('.')]
[os.rename(f, f.replace('C', 'A')) for f in os.listdir('.') if not f.startswith('.')]
[os.rename(f, f.replace('D', 'A')) for f in os.listdir('.') if not f.startswith('.')]
[os.rename(f, f.replace('E', 'A')) for f in os.listdir('.') if not f.startswith('.')]
[os.rename(f, f.replace('F', 'A')) for f in os.listdir('.') if not f.startswith('.')]

我希望能够把它变成某种完整的“替换B,C,D,E和/或F

Q3

我的第三个问题是我怎么能这样做,所以我可以从文件名中删除所有“ - ”,除非部分相同的是“可口可乐”(或其他)

目前我有几个蹩脚的解决方法。但它们效率不高

2 个答案:

答案 0 :(得分:2)

import re
[os.rename(f, re.sub(r'[B-F]', 'A', f)) for f in os.listdir('.') if not f.startswith('.')]

答案 1 :(得分:2)

首先,您确定要使用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匹配字符,即<{>> 与\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]