4、文件与文件夹操作:os模块与pathlib模块
说到文件操作,这可是RPA的看家本领。
你想想看,一个自动化流程里,十有八九都要跟文件打交道。我刚开始写RPA脚本时,最头疼的就是文件路径处理——Windows用反斜杠,Linux用正斜杠,稍不注意就报错。后来用熟了pathlib,才觉得世界清净了。
4.1 os模块 vs pathlib模块:我该用哪个?
Python里有两个主流方案:老牌的os模块,和Python 3.4引入的pathlib。
我个人习惯是这样分的:
- 简单操作(比如判断文件是否存在、获取当前目录)——用
os就够了 - 复杂路径处理(拼接、拆分、批量操作)——用
pathlib,代码更优雅
举个例子你就明白了:
# os模块的老写法
import os
folder = os.path.join("C:\\", "Users", "admin", "Desktop")
files = os.listdir(folder)
# pathlib的新写法
from pathlib import Path
folder = Path("C:/Users/admin/Desktop")
files = list(folder.iterdir())
看出来没?pathlib用/运算符拼接路径,直观多了。我在项目中遇到过好几次因为os.path.join参数顺序搞错导致的bug,换成pathlib后再也没犯过。
pathlib。除非你要兼容Python 2的老代码,否则别纠结。
4.2 核心操作:创建、删除、重命名
这些操作其实就几个函数,但细节挺多。我一个个说。
4.2.1 创建文件夹
from pathlib import Path
# 创建单层目录
Path("my_folder").mkdir(exist_ok=True)
# 创建多层目录(比如 a/b/c)
Path("a/b/c").mkdir(parents=True, exist_ok=True)
exist_ok=True这个参数很实用。如果不加,文件夹已存在时会报错。我刚开始写代码时经常忘了加,结果脚本跑第二次就崩了。
4.2.2 删除文件或文件夹
import os
from pathlib import Path
# 删除文件
os.remove("old_file.txt")
# 或者
Path("old_file.txt").unlink()
# 删除空文件夹
os.rmdir("empty_folder")
# 或者
Path("empty_folder").rmdir()
# 删除非空文件夹(慎用!)
import shutil
shutil.rmtree("non_empty_folder")
shutil.rmtree会直接删除整个目录树,没有回收站!有一次我在测试环境写了个脚本,路径写错了,结果把项目文件夹删了...从那以后,我每次用rmtree前都会先打印路径确认一遍。
4.2.3 重命名与移动
from pathlib import Path
# 重命名
Path("old_name.txt").rename("new_name.txt")
# 移动文件(其实就是重命名路径)
Path("source/file.txt").rename("target/file.txt")
嗯,这里要注意:rename既可以重命名也可以移动。说白了,它就是改了文件的路径名。
4.3 批量操作:重命名、移动、复制
这才是RPA的用武之地。假设你有一堆文件,要批量改名字、分类移动,手点得累死,但Python几行代码搞定。
4.3.1 批量重命名
from pathlib import Path
folder = Path("./downloads")
for i, file in enumerate(folder.iterdir()):
if file.is_file():
new_name = f"report_{i+1}{file.suffix}"
file.rename(folder / new_name)
这个例子把所有文件重命名为report_1.pdf、report_2.docx这样的格式。你想想看,如果每天有几十个下载文件要整理,这段代码能省多少时间。
4.3.2 批量移动(按扩展名分类)
from pathlib import Path
import shutil
source = Path("./downloads")
targets = {
".pdf": Path("./PDFs"),
".docx": Path("./Word"),
".xlsx": Path("./Excel"),
}
for file in source.iterdir():
if file.is_file():
ext = file.suffix.lower()
if ext in targets:
target_folder = targets[ext]
target_folder.mkdir(exist_ok=True)
shutil.move(str(file), str(target_folder / file.name))
这段代码我经常用在整理客户发来的文件上。PDF归PDF,Word归Word,一目了然。
4.3.3 批量复制(带进度感)
from pathlib import Path
import shutil
source = Path("./source_folder")
dest = Path("./backup_folder")
dest.mkdir(exist_ok=True)
for file in source.iterdir():
if file.is_file():
shutil.copy2(str(file), str(dest / file.name))
print(f"已复制: {file.name}")
shutil.copy2比shutil.copy好一点——它会保留文件的元数据(比如修改时间)。我在做备份脚本时都用它。
4.4 实战:整理桌面文件
好了,理论说完了,咱们来点实际的。
我自己的桌面经常乱成一团——截图、PDF、压缩包、临时脚本...每次找文件都头疼。后来我写了个小脚本,一键整理。
from pathlib import Path
import shutil
def organize_desktop():
desktop = Path.home() / "Desktop"
# 定义分类规则
rules = {
"图片": [".png", ".jpg", ".jpeg", ".gif", ".bmp"],
"文档": [".pdf", ".docx", ".txt", ".xlsx", ".pptx"],
"压缩包": [".zip", ".rar", ".7z", ".tar", ".gz"],
"脚本": [".py", ".js", ".bat", ".sh"],
"其他": [] # 兜底
}
for file in desktop.iterdir():
if file.is_file() and not file.name.startswith("."):
moved = False
for folder_name, extensions in rules.items():
if file.suffix.lower() in extensions:
target = desktop / folder_name
target.mkdir(exist_ok=True)
shutil.move(str(file), str(target / file.name))
moved = True
print(f"移动: {file.name} -> {folder_name}")
break
# 没匹配到的归入"其他"
if not moved:
other = desktop / "其他"
other.mkdir(exist_ok=True)
shutil.move(str(file), str(other / file.name))
print(f"移动: {file.name} -> 其他")
if __name__ == "__main__":
organize_desktop()
这段代码的逻辑很简单:
- 遍历桌面所有文件
- 根据扩展名判断属于哪一类
- 移动到对应的分类文件夹
- 没匹配到的统一放"其他"
4.5 总结一下
文件操作这块,说白了就三件事:
- 路径处理——用
pathlib,别自己拼字符串 - 增删改查——记住
mkdir、rename、unlink、rmdir - 批量操作——配合
for循环和shutil模块
你想想看,这些技能组合起来,能做出多少自动化工具?文件备份、日志归档、下载整理...RPA的价值就在这里——把重复劳动交给机器,你去做更有意义的事。
下一章咱们聊聊更高级的:用watchdog模块监控文件变化,实现实时触发。嗯,那个更有意思。