使用glob高效定向检索指定主/子文件夹下匹配文件并实现复制
问题场景
我有如下pandas输出的示例数据集:
现有需求:仅在关联的主文件夹和子文件夹中检索指定文件名,检索到匹配文件后复制到指定路径。当前可运行代码效率极低,每次检索都要遍历所有文件夹和子文件夹。已知参数:main_folder、searchdate均为列表类型,filenames_i_want为待匹配的文件名列表。希望实现直接定位到目标主/子文件夹执行检索,也可接受通过CSV传入路径信息的实现方式。
现有代码如下:
import itertools import glob import shutil from pathlib import Path filenames_i_want = Search_param main_folder=locosearch searchfolder= Search_date TargetFolder = r'C:\ELK\LOGS\XX\DEST' for directory,folder in itertools.product(main_folder, searchfolder): files = glob.glob('Z:/{}/{}/asts_data_logger/*.bz2'.format(directory, folder)) for f in files: current_path = Path(f) cpn = current_path.name if current_path.name in filenames_i_want: print(f"found target file: {f}") shutil.copy2(f, TargetFolder)
优化方案
方案1:基于路径规则直接定位(无需遍历目录文件)
原有代码冗余点在于每次先拉取目标目录下所有.bz2文件再逐个匹配,完全可以直接用待匹配文件名拼接完整路径,判断存在后直接复制,跳过无关文件遍历步骤:
- 先将
filenames_i_want转为集合类型,查找时间复杂度从O(n)降至O(1) - 直接遍历待匹配文件名拼接路径,不需要扫描目标目录下的全部文件
代码实现:
import itertools import shutil from pathlib import Path # 转集合提升查找效率 filenames_i_want = set(Search_param) main_folder = locosearch searchfolder = Search_date TargetFolder = Path(r'C:\ELK\LOGS\XX\DEST') # 提前创建目标目录避免不存在报错 TargetFolder.mkdir(parents=True, exist_ok=True) for directory, folder in itertools.product(main_folder, searchfolder): base_path = Path(f"Z:/{directory}/{folder}/asts_data_logger/") # 仅遍历你需要的文件名,不扫目录下其他文件 for filename in filenames_i_want: full_path = base_path / filename if full_path.exists() and full_path.suffix == '.bz2': print(f"找到目标文件: {full_path}") shutil.copy2(full_path, TargetFolder)
方案2:通过CSV导入预定义路径列表
如果目标检索路径没有固定拼接规则,可以提前将所有需要检索的目录路径存入CSV,读取后直接检索:
- 提前准备CSV文件
path_list.csv,表头设为base_path,每行存储一个目标检索目录的完整路径,例如Z:/业务A/20240501/asts_data_logger/ - 读取CSV路径后直接拼接待匹配文件名判断存在性即可,不需要再做路径规则拼接
代码实现:
import csv import shutil from pathlib import Path filenames_i_want = set(Search_param) TargetFolder = Path(r'C:\ELK\LOGS\XX\DEST') TargetFolder.mkdir(parents=True, exist_ok=True) # 读取CSV中的路径列表 with open('path_list.csv', 'r', encoding='utf-8') as f: reader = csv.DictReader(f) path_list = [row['base_path'] for row in reader] for base_path_str in path_list: base_path = Path(base_path_str) for filename in filenames_i_want: full_path = base_path / filename if full_path.exists(): print(f"找到目标文件: {full_path}") shutil.copy2(full_path, TargetFolder)
效率说明
原有方案时间复杂度为 O(检索目录数 × 单目录平均文件数),单目录下文件越多,执行效率越低;优化后方案时间复杂度为 O(检索目录数 × 待匹配文件名数量),不需要遍历无关文件,在目录下文件数量大的场景下效率提升尤为明显。
内容的提问来源于stack exchange,提问作者Kamikaze K
相关产品推荐
相关产品推荐

