有时我们需要从大量文档中根据一些关键词查找内容,一个一个文档打开查找很费时间,可以把它们合并生成一个文件,查找就方便多了。通过Python实现,步骤如下:
1. 生成需要合并的文件列表
首先导入模块和常量定义
from os import walk,path,listdir
from time import time,sleep
rootdirs = [r'E:\python\merge_all_files'] #需要合并的路径
extends = ['.txt','.py','.sql'] #需要合并的文件扩展名
newfile = 'E:\python\merge_all_files\mergy.txt' #合并后生成的文件名
如果不需要遍历子文件夹,直接遍历所需路径下制定扩展名的文件生成列表:
paths = set()
for rootdir in rootdirs:
for file in listdir(rootdir):
for extend in extends:
if(path.join(rootdir, file).endswith(extend)):
paths.add(path.join(rootdir, file)) #支持中文名称
break
paths = list(paths)
paths.sort(reverse=True)
print(paths)
如果需要遍历子文件夹,不论子文件夹有多少层,均可一次全部遍历完成:
rootdirs = [r'E:\python\merge_all_files']
extends = ['.txt','.py','.sql']
newfile = 'E:\python\merge_all_files\mergy1.txt'
paths = set()
for rootdir in rootdirs:
for root, dirs, files in walk(rootdir):
for file in files:
if path.join(root, file) == newfile:
continue
for extend in extends:
if (path.join(root, file).endswith(extend)):
paths.add(path.join(root, file)) #支持中文名称
break
paths = list(paths)
paths.sort(reverse=True)
print(paths)
2. 将文件列表中的文件内容合并生成文件
直接循环遍历列表中的文件执行合并
#创建新的文件
f = open(newfile,'w',encoding='utf-8')
# 将之前获取到的文件夹(含子文件夹)下所有文件的路径及名称里的内容写进新建的文件里
for i in paths:
try:
f.writelines(i+'\n\n')
for line in open(i,'r',encoding='utf-8'):
f.writelines(line)
f.writelines('\n\n\n\n\n')
print('已完成合并:{}'.format(i))
except:
print('无法读取文件:{}'.format(i))
f.close() #保存并关闭新建的文件
由于文件编码不同,经常会出现读取失败的情况,因此,可列出多个编码,如果失败则尝试下一个编码:
encodes = ("utf-8;gbk;utf-8-sig;gb2312;unicode;ascii").split(';')
excepts = []
#创建新的文件
f = open(newfile,'w',encoding='utf-8')
k = len(paths)
for encode in encodes:
i = len(paths)
if i==0: break
while i:
#i = paths.pop(0)
try:
f.writelines(paths[i-1]+'\n\n')
for line in open(paths[i-1],'r',encoding=encode):
f.writelines(line)
f.writelines('\n\n\n\n\n')
print(paths.pop(i-1),'已完成合并,使用的编码为:{}'.format(encode))
i -= 1
except:
# print('无法读取文件:{}'.format(i))
#excepts.append(i)
i -= 1
f.close() #保存并关闭新建的文件
print('已成功合并{}个文件到{}中'.format(k-len(paths),newfile))
if paths:
print('其中以下文件读取失败\n{}'.format(';\n'.join(paths)))
3. 制作生成小程序
封装成小程序的话,要考虑更多普遍情况,增加一些输入和输出提示。生成小程序后,可以不依赖Python环境,拷贝到任意位置使用,打包方法参考我另一篇文章,生成的exe文件6M左右(高级模式输入我的用户昵称解锁)
from os import walk,path,listdir
from time import time,sleep
while True:
count = 0
name = input("请选择运行模式: 直接回车可进入默认模式 \n1.默认模式: 合并当前文件夹(含子文件夹)下所有.txt/.py/.sql文件,并输出到当前文件夹下mergy.txt文件 \n2.高级模式: 请输入作者名字(英文、中文、拼音均可-_-)解锁 \n3.直接退出: 请输入N\n")
while True:
if name in ['Jogarys','JOGARYS','jogarys','Jogary','JOGARY','jogary','jo','JO','Jo','','N','n','1','3']:
break
elif name=='2':
name = input("请输入作者名字(英文、中文、拼音均可):")
continue
elif count==2:
print("\nSorry,我也帮不了你了,ByeBye!")
break
else:
count += 1
name = input("名字输错啦,你还有{}次机会:".format(3-count))
continue
#运行Python过程中输入文件夹路径及合并后的文件路径及名称
if name in ('N','n','3'):
break
elif count==2:
sleep(3)
break
elif name in ('','1'):
rootdirs = [".\\"]
sub = "Y"
extends = ".txt;.py;.sql".split(';')
encodes = "utf-8;gbk;utf-8-sig;gb2312;unicode;ascii".split(';')
newfile = ".\\mergy.txt"
else:
rootdirs = (input("输入要合并的文件夹路径,多个路径用分号分割,默认为当前路径,例如输入 D:\\1;D:\\2 \n") or (".\\")).split(';')
sub = input("是否遍历所有子文件夹,默认为Y:Y/N \n") or ("Y")
extends = (input("输入要查找的文件扩展名,多个用分号分割,默认为.txt;.py;.sql,例如输入 .txt;.py \n") or (".txt;.py;.sql")).split(';')
encodes = (input("输入编码格式,多个用分号分割,默认为utf-8;gbk;utf-8-sig;gb2312;unicode;ascii\n") or ("utf-8;gbk;utf-8-sig;gb2312;unicode;ascii")).split(';')
newfile = input("输入合并后的文件路径及名称,默认输出到当前目录下mergy.txt,例如输入 D:\my_mergy.txt \n") or (".\\mergy.txt")
#rootdirs = [r'.\AI名企班-BI', r'.\AI核心班-BI'] #固定文件夹路径
#newfile = r'.\merge.py' #固定合并后的新文件路径及名称
paths = set() #存放文件夹(含子文件夹)下所有文件的路径及名称
print("开始合并:")
start = time()
#获取文件夹(含子文件夹)下所有文件的路径及名称
if sub in ("Y","y"):
for rootdir in rootdirs:
for root, dirs, files in walk(rootdir):
# print(root, '\n', dirs, '\n', files, '\n')
for file in files:
if path.join(root, file) == newfile:
continue
for extend in extends:
if (path.join(root, file).endswith(extend)):
paths.add(path.join(root, file)) #支持中文名称
break
else:
for rootdir in rootdirs:
for file in listdir(rootdir):
for extend in extends:
if(path.join(rootdir, file).endswith(extend)):
paths.add(path.join(rootdir, file)) #支持中文名称
break
#print('文件个数:',len(paths))
paths = list(paths)
paths.sort(reverse=True)
#print(paths)
#创建新的文件
excepts = []
f = open(newfile,'w',encoding='utf-8')
# 将之前获取到的文件夹(含子文件夹)下所有文件的路径及名称里的内容写进新建的文件里
k = len(paths)
for encode in encodes:
i = len(paths)
if i==0: break
while i:
#i = paths.pop(0)
try:
f.writelines(paths[i-1]+'\n\n')
for line in open(paths[i-1],'r',encoding=encode):
f.writelines(line)
f.writelines('\n\n\n\n\n')
print(paths.pop(i-1),'已完成合并')
i -= 1
except:
# print('无法读取文件:{}'.format(i))
#excepts.append(i)
i -= 1
f.close() #保存并关闭新建的文件
end = time()
print('已成功合并{}个文件到{}中,用时:{:.2f}秒'.format(k-len(paths),newfile,end-start))
if paths:
print('其中以下文件读取失败\n{}'.format(';\n'.join(paths)))
a = input("是否继续合并其他文件(Y/N)")
if a in ('Y','y'):
continue
else:
break
运行小程序界面如下:
最后奉上我打包好的小程序,可直接下载使用(高级模式输入我的昵称解锁)