You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何提升21.5万条数据与1.4万个文本文件匹配复制的效率?

优化大规模文件匹配与复制的效率方案

嘿,我仔细看了你的代码,完全能理解为什么处理这么大的数据集会慢到离谱——嵌套循环的时间复杂度和冗余操作拖了后腿。咱们来一步步优化,把你的处理时间从“到8月底”压缩到几小时甚至更短:

1. 先把冗余的路径定义简化,批量处理所有季度

你现在定义了几十个单独的路径变量,不仅难维护,还没法批量处理。咱们把源路径和对应的目标路径用字典配对,这样可以循环处理所有季度,不用重复写代码:

# 用字典存储源路径和对应目标路径的映射
path_mapping = {
    'D:/1994_QTR3': 'D:/Required_MDA_1994_QTR3',
    'D:/1994_QTR4': 'D:/Required_MDA_1994_QTR4',
    'D:/1995_QTR1': 'D:/Required_MDA_1995_QTR1',
    # ... 把剩下的季度都按这个格式加进来
    'D:/2002/QTR4': 'D:/Required_MDA_2002_QTR4'
}

2. 重构匹配逻辑:从O(N*M)降到O(N+M)

你的原代码是遍历215000行数据 → 每次遍历14000个文件,这是O(215000*14000)的操作量,完全没必要!反过来,先把需要匹配的文件名存成一个集合(集合的查找是O(1)),然后只遍历一次文件目录,检查文件是否在集合里,这样总操作量是O(215000 + 14000),速度会飞起来:

第一步:预处理Excel里的文件名,转成集合

import os
import pandas as pd
import shutil

# 读取Excel数据,提取需要的文件名
datas = pd.read_excel(r'D:/PhD_Data/Wenrui_Filing_list/1994-2017filingslist_Wenrui_13Jul2020.xlsx')
# 直接提取并处理FILE_NAME列,转成集合
target_files = set(
    datas['FILE_NAME'].str[26:].str.strip().dropna()  # 去掉前26字符、去空格、删除空值
)

第二步:遍历每个源目录,批量复制匹配的文件

for src_dir, dest_dir in path_mapping.items():
    # 确保目标目录存在,避免复制时报错
    os.makedirs(dest_dir, exist_ok=True)
    
    # 遍历源目录下的所有文件
    for file in os.listdir(src_dir):
        src_file_path = os.path.join(src_dir, file)
        # 只处理文件(跳过子目录)
        if os.path.isfile(src_file_path):
            # 检查文件名是否在目标集合里
            if file in target_files:
                print(f"匹配到文件:{file},正在复制到{dest_dir}")
                shutil.copy(src_file_path, dest_dir)

3. 进一步提升复制速度:用硬链接代替复制(如果在同一磁盘)

如果你的源文件和目标目录在同一个磁盘分区,可以用os.link()创建硬链接,而不是shutil.copy()——硬链接不需要复制文件内容,只是给原文件加一个新的“快捷方式”,几乎瞬间完成:

把上面的shutil.copy替换成:

# 先检查目标文件是否已经存在,避免重复创建
dest_file_path = os.path.join(dest_dir, file)
if not os.path.exists(dest_file_path):
    os.link(src_file_path, dest_file_path)

注意:硬链接只能在同一磁盘使用,如果跨磁盘还是用shutil.copy,或者用shutil.copy2(保留文件元数据)。

4. 其他小优化

  • 去掉没用的模块导入:你代码里的glob、csv、xlrd、fnmatch、string都没用到,删掉它们,减少不必要的加载。
  • 用os.scandir()代替os.listdir():os.scandir()比os.listdir()更快,因为它直接返回文件属性,不需要额外调用os.path.isfile():
    with os.scandir(src_dir) as entries:
        for entry in entries:
            if entry.is_file() and entry.name in target_files:
                shutil.copy(entry.path, dest_dir)
    

完整优化后的代码

import os
import pandas as pd
import shutil

# 定义源目录与目标目录的映射
path_mapping = {
    'D:/1994_QTR3': 'D:/Required_MDA_1994_QTR3',
    'D:/1994_QTR4': 'D:/Required_MDA_1994_QTR4',
    'D:/1995_QTR1': 'D:/Required_MDA_1995_QTR1',
    'D:/1995_QTR2': 'D:/Required_MDA_1995_QTR2',
    'D:/1995_QTR3': 'D:/Required_MDA_1995_QTR3',
    'D:/1995_QTR4': 'D:/Required_MDA_1995_QTR4',
    'D:/1996_QTR1': 'D:/Required_MDA_1996_QTR1',
    'D:/1996_QTR2': 'D:/Required_MDA_1996_QTR2',
    'D:/1996_QTR3': 'D:/Required_MDA_1996_QTR3',
    'D:/1996_QTR4': 'D:/Required_MDA_1996_QTR4',
    'D:/1997_QTR1': 'D:/Required_MDA_1997_QTR1',
    'D:/1997_QTR2': 'D:/Required_MDA_1997_QTR2',
    'D:/1997_QTR3': 'D:/Required_MDA_1997_QTR3',
    'D:/1997_QTR4': 'D:/Required_MDA_1997_QTR4',
    'D:/1998/QTR1': 'D:/Required_MDA_1998_QTR1',
    'D:/1998/QTR2': 'D:/Required_MDA_1998_QTR2',
    'D:/1998/QTR3': 'D:/Required_MDA_1998_QTR3',
    'D:/1998/QTR4': 'D:/Required_MDA_1998_QTR4',
    'D:/1999/QTR1': 'D:/Required_MDA_1999_QTR1',
    'D:/1999/QTR2': 'D:/Required_MDA_1999_QTR2',
    'D:/1999/QTR3': 'D:/Required_MDA_1999_QTR3',
    'D:/1999/QTR4': 'D:/Required_MDA_1999_QTR4',
    'D:/2000/QTR1': 'D:/Required_MDA_2000_QTR1',
    'D:/2000/QTR2': 'D:/Required_MDA_2000_QTR2',
    'D:/2000/QTR3': 'D:/Required_MDA_2000_QTR3',
    'D:/2000/QTR4': 'D:/Required_MDA_2000_QTR4',
    'D:/2001/QTR1': 'D:/Required_MDA_2001_QTR1',
    'D:/2001/QTR2': 'D:/Required_MDA_2001_QTR2',
    'D:/2001/QTR3': 'D:/Required_MDA_2001_QTR3',
    'D:/2001/QTR4': 'D:/Required_MDA_2001_QTR4',
    'D:/2002/QTR1': 'D:/Required_MDA_2002_QTR1',
    'D:/2002/QTR2': 'D:/Required_MDA_2002_QTR2',
    'D:/2002/QTR3': 'D:/Required_MDA_2002_QTR3',
    'D:/2002/QTR4': 'D:/Required_MDA_2002_QTR4'
}

# 读取并预处理目标文件名集合
datas = pd.read_excel(r'D:/PhD_Data/Wenrui_Filing_list/1994-2017filingslist_Wenrui_13Jul2020.xlsx')
target_files = set(
    datas['FILE_NAME'].str[26:].str.strip().dropna()
)

# 批量处理每个季度的文件
for src_dir, dest_dir in path_mapping.items():
    os.makedirs(dest_dir, exist_ok=True)
    
    # 使用os.scandir提升遍历效率
    with os.scandir(src_dir) as entries:
        for entry in entries:
            if entry.is_file() and entry.name in target_files:
                dest_file = os.path.join(dest_dir, entry.name)
                # 如果同一磁盘,用硬链接替代复制
                if os.path.splitdrive(src_dir)[0] == os.path.splitdrive(dest_dir)[0]:
                    if not os.path.exists(dest_file):
                        os.link(entry.path, dest_file)
                        print(f"创建硬链接:{entry.name} → {dest_dir}")
                else:
                    shutil.copy2(entry.path, dest_file)
                    print(f"复制文件:{entry.name} → {dest_dir}")

print("所有文件处理完成!")

内容的提问来源于stack exchange,提问作者Dale Addison

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 18:52:58