在文件重命名中使用正则表达式排除字符,Python?

0 投票
2 回答
885 浏览
提问于 2025-04-18 06:26

我正在尝试重命名文件,让它们包含一个ID,后面跟着一个-(整数)。这些文件通常是以这种方式发给我的,但有时它们的格式是1234567-1(crop to bottom).jpg。

我一直在尝试使用以下代码,但我的正则表达式似乎没有任何效果。之所以要遍历,是因为我们需要处理包含很多图片的大目录树。

def fix_length():
    for root, dirs, files in os.walk(path):
        for fn in files:
            path2 = os.path.join(root, fn)
            filename_zero, extension = os.path.splitext(fn)
            re.sub("[^0-9][-]", "", filename_zero)
            os.rename(path2, filename_zero + extension) 

fix_length()

我在re.sub这一行之前和之后插入了打印语句,结果显示filename_zero没有变化(也就是说,还是1234567-1(crop to bottom),这不是我想要的结果)

这引发了一个异常,因为重命名时试图创建一个已经存在的文件。

我以为可能是正则表达式中的[-]导致了问题,但我去掉它后再运行,我本来期待得到12345671.jpg,但这也不行。看来我的正则表达式出错了,或者是我没用好正则表达式。

如果能提供一些见解,我将非常感激。

作为后续,我已经根据大家的帮助,找到了一个适合我具体问题的解决方案。

path = 'C:\Archive'
errors = 'C:\Test\errors'
num_files = []

def best_sol():
    num_files = []
    for root, dirs, files in os.walk(path):
        for fn in files:
            filename_zero, extension = os.path.splitext(fn)
            path2 = os.path.join(root, fn)
            ID = re.match('^\d{1,10}', fn).group()
            if len(ID) <= 7:
                if ID not in num_files:
                    num_files = []
                    num_files.append(ID)
                    suffix = str(len(num_files))
                    os.rename(path2, os.path.join(root, ID + '-' + suffix + extension)) 
                else:
                    num_files.append(ID)
                    suffix = str(len(num_files))
                    os.rename(path2, os.path.join( root, ID + '-' + suffix +extension)) 
            else:
                shutil.copy(path2, errors)
                os.remove(path2)

这段代码根据文件名中的前10个数字字符生成一个ID。我接着使用列表来存储这个ID的实例,并根据列表的长度添加后缀。第一个文件会有-1,第二个文件会有-2,依此类推……

我只对长度为7的ID感兴趣(或者说应该只关注这些),但允许读取最多10个字符,以防人们在标记时出错。所有ID长度超过7的文件会被移动到一个文件夹里,以便我们进一步调查。

感谢你们让我走上了正确的方向。

2 个回答

0
new_filename = re.sub(r'^([0-9]+)-([0-9]+)', r'\g1-\g2', filename_zero)

试试这个正则表达式,我希望这就是Python中正则表达式的用法,我不常用。你似乎也忘了把re.sub返回的值赋给filename_zero这个变量。

2

re.sub() 会返回修改后的字符串,但你没有使用这个返回值。

你需要把结果重新赋值给 filename_zero

filename_zero = re.sub("[^\d-]", "", filename_zero)

我也修正了你的正则表达式;这个表达式会去掉基础文件名中所有不是数字或破折号的字符:

>>> re.sub(r'[^\d-]', '', '1234567-1(crop to bottom)')
'1234567-1'

记住,字符串是不可变的,你不能直接修改它们。

如果你只想要开头的数字,加上可选的破折号和数字后缀,那就选择要保留的字符,而不是去掉你不想要的:

filename_zero = re.match(r'^\d+(?:-\d)?', filename_zero).group()

撰写回答