Python 的 os 模块提供了一系列访问系统中文件的方法。使用 getcwd() 方法可以获得当前的工作路径,使用 listdir() 方法可以列出路径中的所有文件和文件夹,至于是文件还是文件夹,需要使用 os.path 中的 isdir() 方法来判断。用这些方法遍历文件夹比较麻烦,因此提供了一个 walk 方法用于遍历文件夹。

walk 方法的设计比较巧妙。它的参数是要遍历的目录,返回一个迭代器,由 tuple 组成,每个 tuple 中有三个元素,分别是 root 即目前正在遍历的路径, ds 即当前路径下的所有文件夹名,和 fs 即当前路径下的所有文件名。下面分三个使用场景并提供示例代码。

为所有文件建立索引

网络上下载的电子书由于量很大,通常是分不同文件夹保存的,有时会有三、四级深。要想知道硬盘中有哪些电子书以便查找,需要对书名建立索引。这里使用简单的方式,即把书名和对应路径保存在文本文件中,这样使用文本编辑器自带的搜索功能即可找到电子书。代码如下:

1
2
3
4
5
6
7
8
9
import os

path = r"D:\myfolder"
records = ""
for root, ds, fs in os.walk(path):
for f in fs:
records += f"{os.path.join(root)}\\{f}\n"
with open("index.txt", "w", encoding="utf-8") as f:
f.write(records)

删除重复文件

在使用下载器下载文件夹时,有时下载中断后,又重新下载时,之前下载的文件会重复出现一遍。当然这可以通过其他方式避免,比如先删掉下载的文件,或到子文件夹中下载等。但是如果出现了大量散落的重复文件,就可以使用 walk 来查找并删除。在我的英文版 Windows 系统中,出现重复文件时会在文件名之后、扩展名之前加入一个 (1) 。用这一特征即可通过正则表达式来找到重复文件并删除。对于其他操作系统也有可以识别的特征,只需要微调正则表达式。代码如下:

1
2
3
4
5
6
7
8
import os, re

path = r"D:\myfolder"
for root, ds, fs in os.walk(path):
for f in fs:
if re.search(r"\([1-9]\)\.\S{2,4}$", f):
abspath = os.path.join(root, f)
os.remove(abspath)

上面的正则表达式可以匹配多次复制、扩展名为2-4个字符的文件。

批量重命名

使用相机导入的照片命名上通常无显著意义,有时还会按日期分文件夹储存。这时可以使用 walk 来遍历,并使用 shutil 移动到硬盘中,再更改文件名。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
import os, shutil

path = r"E:\DCIM"
target = r"D:\myphotos\thisyear"
i = 1
for root, ds, fs in os.walk(path):
for f in fs:
if re.match(r"IMG\d*\.JPG", f):
shutil.move(
os.path.join(root, f),
os.path.join(target, f"mytrip{i}.JPG")
)
i += 1