告别手工复制粘贴:3个Python脚本技巧,10秒合并上千个文本文件
📑 目录导读
- 为什么你需要脚本合并文本?(场景与痛点)
- 准备工作:环境与文件命名规范
- 核心方案一:基础版——
os模块批量读取与追加 - 核心方案二:进阶版——处理编码混乱与路径递归
- 核心方案三:实战版——按文件名排序并自动添加分隔符
- 高频问答(FAQ)与踩坑指南
- 脚本的进阶优化与自动化扩展
为什么你需要脚本合并文本?——场景与痛点
日常工作中,你是否面临过以下困境?数据分析师需要汇总几十个CSV日志;作者需要把每章存为独立TXT的书籍合并;运维人员需要拼接多台服务器的配置文件,如果靠手动打开、复制、粘贴,不仅耗时(例如100个文件至少需要20分钟),还极易出错(漏行、乱序、编码乱码)。

用脚本合并的核心价值在于:确定性(每次执行结果一致)与批量处理能力(一秒处理上千文件),这不仅仅是节省时间,更是将重复劳动转化为可复用的自动化流程,这正是效率工具的底层逻辑。
准备工作:环境与文件命名规范
在写脚本前,请先明确两点:
- 运行环境:建议使用Python 3.8+(无需额外安装库,仅用标准库)。
- 目录结构:将所有待合并的TXT文件放在同一个文件夹内(如
D:\data_folder),并确认这些文件没有重名,若需按特定顺序合并,文件名建议带数字前缀(如001_chapter.txt,002_chapter.txt),否则脚本默认按系统文件名的字母顺序处理(通常为ASCII码排序)。
核心方案一:基础版——os模块批量读取与追加
这是最简洁的入门脚本,适合所有文件编码均为UTF-8且无子目录的情况。
import os
folder_path = "D:\\data_folder" # 替换为你的文件夹路径
output_file = "D:\\merged_result.txt" # 输出文件路径
with open(output_file, 'w', encoding='utf-8') as outfile:
for filename in os.listdir(folder_path):
if filename.endswith('.txt'): # 只处理txt文件
file_path = os.path.join(folder_path, filename)
with open(file_path, 'r', encoding='utf-8') as infile:
outfile.write(infile.read())
outfile.write("\n") # 每个文件之间加换行,避免粘行
代码逻辑解读:
os.listdir()列出当前目录所有文件。- 每次打开一个源文件,用
read()读取全部内容,通过write()直接写入目标文件。 - 关键的
"\n":防止两个文件最后一行与第一行连在一起。
核心方案二:进阶版——处理编码混乱与路径递归
现实场景中,部分老旧TXT文件可能是GBK或ANSI编码,直接读取UTF-8会报错,文件可能分散在子文件夹中,此版本解决两大痛点。
import os
def merge_files(src_root, dest_file, encodings=('utf-8', 'gbk', 'ansi')):
with open(dest_file, 'w', encoding='utf-8') as outfile:
# 使用 os.walk 递归遍历所有子目录
for root, dirs, files in os.walk(src_root):
for filename in files:
if filename.endswith('.txt'):
file_path = os.path.join(root, filename)
# 尝试用不同编码读取
for enc in encodings:
try:
with open(file_path, 'r', encoding=enc) as infile:
outfile.write(infile.read())
outfile.write("\n")
break # 成功读取则跳出编码循环
except UnicodeDecodeError:
continue # 尝试下一种编码
else:
print(f"警告:无法解码 {file_path},已跳过")
merge_files("D:\\source_dir", "D:\\merged_output.txt")
进阶逻辑亮点:
os.walk递归遍历所有子目录,无需手动整理。- 用
try...except尝试多种编码,当utf-8失败时自动尝试gbk,避免了脚本中断。 else子句(与for配合):只有当所有编码尝试失败时才执行警告。
核心方案三:实战版——按文件名排序并自动添加分隔符
当你合并的是小说章节或日志,希望每个文件内容前有清晰的分隔标记,同时按文件名数字排序,而非字母序(避免10排在2前面),此方案最合适。
import os
import re
folder_path = "D:\\chapters"
output_file = "D:\\novel_full.txt"
def natural_key(text):
# 自然排序:提取文件名中的数字用于排序
return [int(part) if part.isdigit() else part.lower() for part in re.split(r'(\d+)', text)]
# 获取所有txt文件,并按自然顺序排序
txt_files = [f for f in os.listdir(folder_path) if f.endswith('.txt')]
txt_files.sort(key=natural_key)
with open(output_file, 'w', encoding='utf-8') as outfile:
for idx, filename in enumerate(txt_files, start=1):
file_path = os.path.join(folder_path, filename)
# 写入分隔头,===== 第1章 文件名 =====
outfile.write(f"\n===== 文件 {idx}: {filename} =====\n")
with open(file_path, 'r', encoding='utf-8') as infile:
outfile.write(infile.read())
outfile.write("\n")
排序机制详解:
函数natural_key用正则re.split将文件名拆分为“字母和数字”的交替列表,排序时,txt会排在txt之前(因为先按数字2和10比较,而非字符串'10'小于'2')。
❓ 高频问答与踩坑指南
Q1:合并后文件中间出现空行或者缺失最后一个字符?
A:源文件最后一行没有换行符时,write(infile.read())之后紧跟着下一个文件的内容,解决方案是在每个文件写入后强制write("\n"),或者使用infile.readline()循环逐行写入。
Q2:合并大量文件(超过1000个)时内存爆掉怎么办?
A:不要用read()一次性读取大文件,改为逐行复制:
for line in infile:
outfile.write(line)
这样内存占用恒定,速度稍慢但稳定。
Q3:如何合并非TXT格式(如.log, .csv)?
A:将脚本中的filename.endswith('.txt')改为if filename.endswith(('.txt', '.log', '.csv')), 或者直接使用if os.path.isfile(file_path):选择所有文件(但会包含不需要的临时文件,需谨慎)。
Q4:输出文件有乱码,如何解决?
A:首先确定输入文件的常见编码(用记事本打开正常显示但脚本乱码),建议统一输出为UTF-8(脚本已指定),并确保输入尝试编码顺序包含utf-8-sig(处理带BOM的UTF-8文件)。
脚本的进阶优化与自动化扩展
上述脚本已满足90%的合并需求,但若想更进一步:
- 添加日志记录:将每次合并的文件列表、时间戳写入一个
merge_log.txt,方便追溯。 - 命令行参数化:使用
sys.argv或argparse,无需修改代码即可指定输入输出路径。 - 定时自动合并:在Windows任务计划程序或Linux Crontab中设置定时运行,实现每日自动汇总日志。
将上述代码保存为.py文件,用python merge_script.py一键运行,从此,你只需拖拽文件夹,喝杯咖啡,上千个文件就已完美融合为一个整洁的文档——这就是自动化脚本的魅力所在。