python怎么修改文件名?手把手教你轻松批量改名!
哎呀,说到这python怎么修改文件名啊,这事儿我可太有经验了!想想看,以前我刚接触编程那会儿,处理一大堆文件,比如照片啦、下载的文档啦,名字乱七八糟的,看得人心烦。一个个手动去点,去改,那叫一个折磨!手指头都快戳麻了。特别是那种有规律的,比如“DSC_0001.JPG”、“DSC_0002.JPG”……想改成“旅游照片_001.JPG”、“旅游照片_002.JPG”,光想想就头皮发麻,更别提真动手了。
那时候我就在想,肯定有更优雅、更有效率的方法。后来越来越深入地接触 Python,才发现,嘿,这工具简直是批量改名的神!不是吹牛,掌握了用 Python 来修改文件名,你的工作效率能噌噌地往上涨,而且那种成就感,真是改十个文件都比不上!
那么,这python怎么修改文件名,具体要怎么操作呢?其实核心呢,主要就是Python标准库里的一个模块:os
。没错,就是它!这个os
模块,顾名思义,就是跟操作系统打交道的,文件啊、目录啊这些操作,它都能搞定。
咱们先来个最简单的例子,就改一个文件的名字。假设你有个文件叫 test.txt
,你想把它改成 hello_world.txt
。怎么弄?
```python
import os
定义旧文件名和新文件名
old_name = "test.txt"
new_name = "hello_world.txt"
try:
# 使用 os.rename() 方法
os.rename(old_name, new_name)
print(f"文件 '{old_name}' 已成功更名为 '{new_name}'")
except FileNotFoundError:
print(f"错误:文件 '{old_name}' 不存在。")
except FileExistsError:
print(f"错误:文件 '{new_name}' 已存在。")
except Exception as e:
print(f"发生未知错误:{e}")
```
看看,多简洁!就这么几行代码,os.rename()
,传入旧的名字和新的名字,一句话的事儿!这比你右键、重命名、输入新名字、回车,可快多了,尤其当你要反复改名或者写脚本的时候。这里我特意加了个 try...except
块,干啥用的呢?是为了让代码更健壮啊!你想想,如果 test.txt
压根儿就不存在,或者 hello_world.txt
已经有了,直接运行 os.rename()
会报错,程序就崩了。加上这个,就能优雅地处理这些情况,给出友好的提示,不是挺好吗?这就像你走路,地上有个坑,你知道绕一下总比直接掉进去要强。
但咱们的 ultimate goal (最终目标) 可是批量改名啊!改一个文件只是小试牛刀。怎么批量改呢?这就要用到 os
模块的另一个好东西了:os.listdir()
。这个方法能列出指定目录下的所有文件和文件夹的名字。
想象一下这个场景:你有个文件夹,里面全是照片,名字都是相机默认的 IMG_xxxx.JPG
格式,你想把它们改成 我的照片_日期_序号.JPG
。这种有规律的批量操作,手动?想都别想!Python 在这时就 shine (闪耀) 了。
咱们来一步步分解这个批量改名的过程:
- 指定目录:你得告诉 Python 你的文件都在哪个文件夹里。
- 获取文件列表:用
os.listdir()
把目录里的所有文件名都拿出来。 - 遍历文件列表:一个个地看这些文件名。
- 判断是否需要改名:有些文件你可能不想改,比如子文件夹什么的,所以得有个判断。
- 构造新文件名:根据你的规则,生成一个新的文件名。这步最灵活,也是体现你编程功力的地方!可以加前缀、加日期、加序号、替换字符串、甚至用正则表达式玩儿高级的。
- 执行改名:用
os.rename()
把旧名字改成新名字。 - 处理潜在问题:比如新名字和旧名字一样,或者目标文件夹下已经有同名文件了。
好,咱们来个具体的例子,把一个文件夹里所有以 IMG_
开头的 .JPG
文件,改成 旅游照片_
开头,后面加上原来的序号。
```python
import os
指定要处理的目录
directory = "/Users/yourname/Pictures/Vacation" # 改成你自己的文件路径!重要!
进入目录,这样 os.rename 就不需要完整的路径了
如果不切换目录,os.rename 需要 full path (完整路径)
os.chdir(directory)
print(f"正在处理目录:{os.getcwd()}") # 打印当前工作目录确认一下
count = 0
遍历目录下的所有文件和文件夹
for filename in os.listdir():
# 判断是不是文件,并且是我们要找的类型 (这里是 .JPG)
# os.path.isfile() 判断是不是文件
# filename.endswith('.JPG') 判断文件名是否以 .JPG 结尾 (注意大小写,可以改成 .lower().endswith('.jpg') 忽略大小写)
# filename.startswith('IMG_') 判断文件名是否以 IMG_ 开头
if os.path.isfile(filename) and filename.endswith('.JPG') and filename.startswith('IMG_'):
# 提取序号部分,比如从 'IMG_1234.JPG' 里拿出 '1234'
# 注意这里只是一个简单的例子,实际情况可能更复杂
try:
# 找到 '' 的位置,然后切片,再去掉 .JPG 后缀
# 这段逻辑可能需要根据你的实际文件名格式调整!非常重要!
parts = filename.split('')
if len(parts) > 1:
# 假设 '' 后面就是序号,且在 .JPG 前
# 比如 IMG_1234.JPG -> parts = ['IMG', '1234.JPG']
# 或者 IMG_ABC_1234.JPG -> parts = ['IMG', 'ABC', '1234.JPG']
# 这里我们假设是 IMG_xxxx.JPG 这种简单的,直接取最后一个 _ 后面部分
# 这种方式可能不严谨,更 robust 的方式是使用正则表达式或者更精细的字符串处理
# 咱们先来个简单粗暴的:假设文件名就是 IMG_xxxx.JPG
# new_base_name = filename[4:-4] # 从第5个字符开始到倒数第4个字符结束 (IMG 和 .JPG 各占4个字符)
# 但是这样取出来的是 '1234'
# 如果想保留序号的格式,比如 '0001', '0002'
# 可以这样做:
base_name, ext = os.path.splitext(filename) # 分离文件名和扩展名,比如 'IMG_1234', '.JPG'
if base_name.startswith('IMG_'):
original_number_str = base_name[4:] # 提取 '1234' 部分
# 构造新的文件名,比如 '旅游照片_1234.JPG'
new_filename = f"旅游照片_{original_number_str}{ext}"
# 检查新文件名是否已经存在,避免覆盖!
if not os.path.exists(new_filename):
# 执行改名操作
os.rename(filename, new_filename)
print(f"成功更名:'{filename}' -> '{new_filename}'")
count += 1
else:
print(f"跳过:'{new_filename}' 已存在。'{filename}' 未改名。")
else:
print(f"跳过:文件名 '{filename}' 格式不符合预期。")
except Exception as e:
print(f"处理文件 '{filename}' 时发生错误:{e}")
print(f"\n批量改名完成。共处理了 {count} 个文件。")
```
看到没?这段代码比前面那个改单个文件的复杂一点,但也就那么回事儿。关键在于那个 for filename in os.listdir():
循环,它把目录里的每个文件都过一遍。然后在循环里,我们加了各种判断:是不是文件?是不是 .JPG
结尾?是不是 IMG_
开头?这些都是为了精确锁定咱们的目标文件,不误伤无辜。
构造新文件名那块,我用了 f-string
(f"旅游照片_{original_number_str}{ext}"
),这玩意儿贼方便,直接在字符串里嵌入变量。当然,你也可以用传统的字符串拼接或者 .format()
方法,看个人喜好。这里我只是简单地在前面加了个前缀,保留了原来的数字序号和扩展名。如果你想更花哨点,比如加个今天的日期?没问题!
```python
import datetime
... (前面部分代码相同) ...
now = datetime.datetime.now()
date_str = now.strftime("%Y%m%d") # 格式化日期,比如 20231027
在构造新文件名的地方修改
if os.path.isfile(filename) and filename.endswith('.JPG') and filename.startswith('IMG_'):
try:
base_name, ext = os.path.splitext(filename)
if base_name.startswith('IMG_'):
original_number_str = base_name[4:]
# 新文件名加入日期
new_filename = f"旅游照片_{date_str}_{original_number_str}{ext}"
if not os.path.exists(new_filename):
os.rename(filename, new_filename)
print(f"成功更名:'{filename}' -> '{new_filename}'")
count += 1
else:
print(f"跳过:'{new_filename}' 已存在。'{filename}' 未改名。")
else:
print(f"跳过:文件名 '{filename}' 格式不符合预期。")
except Exception as e:
print(f"处理文件 '{filename}' 时发生错误:{e}")
... (后面部分代码相同) ...
```
看到了吧?导入 datetime
模块,获取当前日期,格式化一下,然后塞进新文件名里,就这么简单!你想加什么、怎么加,完全取决于你的需求和你的创意。
再比如,你有一堆下载下来的电影文件,名字是 [高清天堂www.xyz.com]肖申克的救赎HD.mp4
这种,你只想保留 肖申克的救赎HD.mp4
。这种时候,你可能需要用到字符串的替换或者更高级的手段,比如正则表达式。
用字符串替换:
```python
... (前面部分代码相同) ...
在构造新文件名的地方修改
if os.path.isfile(filename) and filename.endswith('.mp4'):
try:
# 移除特定的前缀
if filename.startswith('[高清天堂www.xyz.com]'):
new_filename = filename.replace('[高清天堂www.xyz.com]', '') # 用空字符串替换掉前缀
if not os.path.exists(new_filename):
os.rename(filename, new_filename)
print(f"成功更名:'{filename}' -> '{new_filename}'")
count += 1
else:
print(f"跳过:'{new_filename}' 已存在。'{filename}' 未改名。")
else:
print(f"跳过:文件名 '{filename}' 格式不符合预期。")
except Exception as e:
print(f"处理文件 '{filename}' 时发生错误:{e}")
... (后面部分代码相同) ...
```
这里用了 filename.replace('[高清天堂www.xyz.com]', '')
,直接把那个烦人的前缀替换掉了。简单直接有效。
如果规则更复杂,比如文件名里有很多奇奇怪怪的字符,你想把它们都去掉,或者只保留字母数字下划线什么的,这时候就轮到正则表达式大显身手了。Python 里处理正则表达式的模块是 re
。不过这玩意儿有点儿“进阶”,初学者可能会觉得有点绕,但一旦掌握了,处理字符串简直不要太方便!
```python
import os
import re # 导入正则表达式模块
指定要处理的目录
directory = "/path/to/your/files" # 改成你自己的文件路径!
os.chdir(directory)
print(f"正在处理目录:{os.getcwd()}")
count = 0
遍历目录下的所有文件和文件夹
for filename in os.listdir():
if os.path.isfile(filename): # 只处理文件
try:
# 定义一个正则表达式模式,比如只保留字母、数字、下划线、点
# [a-zA-Z0-9_.]+ 匹配一个或多个这些字符
# re.findall() 找到所有匹配的部分
# ''.join() 把找到的部分拼接起来
# 这个正则表达式需要根据你的实际需求来写!很灵活!
# 比如,只想保留电影名和扩展名,去除括号及里面的内容
# pattern = re.compile(r'^(.?)[【[].?】]$') # 匹配以 [ 或 【 开头,以 ] 或 】 结尾的中间内容
# match = pattern.match(filename)
# if match:
# # 新文件名 = match.group(1) + match.group(2)
# # print(f"尝试改名 (正则):'{filename}' -> '{new_filename}'")
# pass # 这里需要根据实际情况写逻辑
# 咱们来个简单点的正则:去除文件名中的所有非字母、数字、下划线、点以外的字符(除了扩展名之前的部分)
# 先分离文件名和扩展名
base_name, ext = os.path.splitext(filename)
# 只对文件名部分进行正则处理
cleaned_base_name = re.sub(r'[^\w.]+', '', base_name) # 替换掉所有非单词字符(\w即字母数字下划线)和非点字符
# 如果清理后的文件名是空的,可能需要加个默认名或者跳过
if not cleaned_base_name:
cleaned_base_name = "cleaned_file" # 提供一个默认名
new_filename = cleaned_base_name + ext
# 增加一个防止新旧文件名相同导致出错的检查
if new_filename == filename:
print(f"跳过:文件名 '{filename}' 清理后未改变。")
continue # 跳过本次循环
# 检查新文件名是否存在,避免覆盖
if not os.path.exists(new_filename):
os.rename(filename, new_filename)
print(f"成功更名 (正则):'{filename}' -> '{new_filename}'")
count += 1
else:
print(f"跳过:'{new_filename}' 已存在。'{filename}' 未改名。")
except Exception as e:
print(f"处理文件 '{filename}' 时发生错误:{e}")
print(f"\n批量改名 (正则) 完成。共处理了 {count} 个文件。")
```
看到没,用 re.sub()
方法,传入正则表达式模式、替换成的字符串(这里是空字符串),以及要处理的原始字符串,它就能帮你把所有匹配模式的地方都替换掉。正则表达式的学习曲线是陡峭了点,但回报是巨大的,尤其在处理文本和字符串的时候。
当然了,用 Python 修改文件名还有很多细节需要注意。比如:
- 权限问题:你的脚本是否有权限在目标文件夹进行写操作?有时候管理员权限是很重要的。
- 文件锁:文件是不是正在被别的程序使用?如果文件被锁定了,
os.rename()
可能会失败。 - 路径问题:你是使用绝对路径还是相对路径?
os.chdir()
可以让你切换到目标目录,然后直接使用文件名进行操作,省去写完整路径的麻烦,但也需要注意当前工作目录是否正确。不使用os.chdir()
的话,os.rename()
需要旧文件和新文件的完整路径。 - 覆盖问题:如果你生成的新文件名已经存在,
os.rename()
默认会覆盖,这可能不是你想要的!所以,在执行改名之前,最好用os.path.exists(new_filename)
检查一下新文件是否存在,如果存在,就跳过或者改成别的名字(比如在后面加个序号)。我上面的代码示例里已经加入了这个检查,强烈建议你保留! - 回滚机制:万一你批量改名改错了,怎么恢复?最好的办法是先备份一下要改名的文件,或者在改名时把旧名字记录下来,方便以后恢复。不过对于简单的改名,如果不是特别重要,可能就直接跑了。但对于关键文件,务必三思,备份!备份!备份!重要的事情说三遍!
所以说,python怎么修改文件名这事儿,真不是一句两句就能说清的。它给了你强大的工具,但怎么用、用得多好,取决于你对 Python 的理解和对具体问题的分析。从改单个文件到批量处理,从简单的字符串操作到复杂的正则表达式,Python 都能胜任。
对我个人来说,用 Python 来修改文件名,不仅仅是提高了效率,更是一种掌控感。看着那些曾经杂乱无章的文件在你的脚本下变得井井有条,那种感觉,嘿嘿,别提多爽了!而且,一旦你掌握了用 Python 处理文件和目录,你会发现它还能帮你做更多有趣的事情,比如文件分类、查找重复文件、自动整理下载等等。Python 的 os
模块只是冰山一角,还有 shutil
(文件复制、移动等高级操作),glob
(查找符合特定模式的文件路径)等等,都是文件处理的好帮手。
总而言之,python怎么修改文件名这个问题,答案是肯定的:能,而且能做得非常漂亮!拿起你的编辑器,写几行代码,去感受一下 Python 在文件管理上的魔力吧!相信我,一旦你习惯了这种自动化、批处理的方式,你就再也回不去手动改名的“原始时代”了。去试试吧,你不会后悔的!