比较os.listdir()与os.walk()
用os.listdir(path)可查询path目录下的所有文件,用os.walk(path)可查询path目录及其子目录下的所有文件。
但是os.walk()不能控制遍历文件树的深度,而且默认会忽略发生的异常,把没有访问权限的目录直接判定为空目录。如下:
>>> import os
>>> os.listdir("/root") # 使用os.listdir()查询,遇到异常会直接抛出
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
PermissionError: [Errno 13] Permission denied: '/root'
>>> list(os.walk("/root")) # os.walk()默认会忽略发生的异常
[]
>>> list(os.walk("/root", onerror=print)) # 可传入onerror参数,记录发生的异常
[Errno 13] Permission denied: '/root'
[]
查找所有文件
基于os.walk()自定义一个函数:每次迭代时遍历一个子目录。
采用生成器模式,可以让程序一边遍历文件,一边进行处理。
def find_all_files(path: str = '.', onerror=print):
"""
查找`path`目录及其子目录下的所有文件,返回一个生成器。
- `path`: 一个已存在的目录。
- `onerror`: 记录异常的函数名。
"""
for basepath, dirnames, filenames in os.walk(path, onerror=onerror):
paths = []
for i in dirnames + filenames:
paths.append(os.path.join(basepath, i))
yield paths
if __name__ == "__main__":
for paths in find_all_files("."):
print(paths)
查找并筛选文件
基于os.listdir()自定义一个函数,查找文件,控制查找文件树的深度,并根据shell通配符、正则表达式筛选文件。
import os
import fnmatch
import re
def find_file(directory='.', depth=-1, pattern=None, re_pattern=None, onerror=print) -> list:
"""
查找文件,并进行筛选。
- `directory`: 一个已存在的目录。
- `depth`: 查找文件树的最大深度。如果值为负数,则无限深度。
- `pattern`: 根据shell通配符筛选文件名。
- `re_pattern`: 根据正则表达式筛选文件名。
- `onerror`: 一个可调用的参数,用于记录报错。
工作在递归模式。如果处理上千个文件,可能要花费好几秒。
示例:
>>> find_file('.', pattern='*.py')
>>> find_file('.', re_pattern='.*.py')
"""
if not os.path.isdir(directory):
raise ValueError("{} is not an existing directory.".format(directory))
try:
file_list = os.listdir(directory)
except PermissionError as e: # Sometimes it does not have access to the directory
onerror("PermissionError: {}".format(e))
return -1
path_list = []
for filename in file_list:
path = os.path.join(directory, filename)
if depth != 0 and os.path.isdir(path):
sub_list = find_file(path, depth-1, pattern, re_pattern, onerror)
if sub_list != -1:
path_list.extend(sub_list)
continue
if pattern and not fnmatch.fnmatch(filename, pattern):
continue
if re_pattern and not re.findall(re_pattern, filename):
continue
path_list.append(path)
return path_list
关于路径分隔符 / 和 \
- 类Unix平台、Web使用正斜杠 / 作为路径分隔符,而Windows使用反斜杠 \ 作为路径分隔符,所以在字符串出现中时要转义或者加上前缀r。
- Python访问某个路径时可以用正斜杠也可以用反斜杠,比如 “C:/Users”、“C:\Users”、r"C:\Users",因为Python内置的函数会自动识别并转换这几种路径分隔符。