前言
做深度学习等模型训练工作时经常需要批量处理一些数据文件,为了方便查阅,笔者将会在本篇博客持续更新汇总一些常用的数据文件批量处理脚本,文中大多脚本都参考了网络现有资源加以改进,给出了多种实现方法(包括标准库和第三方库的方法以及自己编写的更接近底层的、可以根据需求灵活改变的方法),文章中将会介绍脚本作用以及需要修改的地方并给出使用示例。
一、基础脚本
1、获取某一文件夹下指定文件类型的文件名
Input
- file_dir:待获取文件名的文件夹路径
- file_type(可选):指定文件类型(笔者这里只写了指定一种文件类型,如果需要提取多种的话可以多次调用,或者在文件类型判断中加入
或判断
即可)
Output
- file_dir 文件夹下指定文件类型的文件名列表(不一定按照在文件夹下的查看顺序)
import os
def get_file_name(file_dir,file_type=''):#默认为文件夹下的所有文件
lst = []
for root, dirs, files in os.walk(file_dir):
for file in files:
if(file_type == ''):
lst.append(file)
else:
if os.path.splitext(file)[1] == str(file_type):#获取指定类型的文件名
lst.append(file)
return lst
使用Python标准库
- glob模块的glob方法
from glob import glob
# glob获得路径下所有文件路径
#‘*’表示任意,如果文件命是任意,那么就是所有文件
# 可根据需要修改,获得指定命名格式的文件
src_file_list = glob(file_dir + '*')
通过glob方法还可以实现提取规定命名形式
的文件,进一步了解可以看python之glob模块以及根据路径获取文件名
- os模块
import os
os.listdir(file_dir)
2、批量修改某一文件夹下的文件类型或命名
只需要在第一个脚本的基础上,对获取到的文件进行重命名即可(文件名称包括文件显示名以及文件扩展类型名称,改变文件类型本质也是重命名),重命名需要用到Python re库中的replace方法以及os库中的rename方法。
读者只需要根据需求修改Newdir的命名形式即可。
import os
import re
# 获取文件夹file_dir下指定类型file_type的所有文件名
def file_name(file_dir,file_type=''):#默认为文件夹下的所有文件
lst = []
for root, dirs, files in os.walk(file_dir):
for file in files:
if(file_type == ''):
lst.append(file)
else:
if os.path.splitext(file)[1] == str(file_type):#获取指定类型的文件名
lst.append(file)
return lst
file_dir = "C:/Users/MECHREVO/Desktop/test/"
files = file_name(file_dir)
# 对文件名进行批量重命名
for name in files:#遍历所有文件
Olddir= file_dir + name
# 根据自己的需要对文件名称进行修改,生成新的文件名称
Newdir= file_dir + name.replace(".xml",".txt")
os.rename(Olddir,Newdir)#重命名
使用示例
(修改文件类型)
处理前:
处理后:
3、批量复制文件到指定的文件夹下
更简便的方法:用Python复制文件的9个方法
function
- 复制一个文件到目标路径下(结合脚本1使用,先获取需要复制的文件路径,多次调用实现批量复制)
Input
- srcfile:待复制移动的文件路径
- dstpath:目标路径
import shutil
import os
# 复制文件到指定的目录
# srcfile 需要复制、移动的文件
# dstpath 目的地址
def mycopyfile(srcfile,dstpath): # 复制函数
if not os.path.isfile(srcfile):
print ("%s not exist!"%(srcfile))
else:
fpath,fname=os.path.split(srcfile) # 分离文件名和路径
if not os.path.exists(dstpath):
os.makedirs(dstpath) # 创建路径
shutil.copy(srcfile, dstpath + fname) # 复制文件
print ("copy %s -> %s"%(srcfile, dstpath + fname))
使用示例
二、进阶脚本
1、多个Voc数据集的融合
当你搜索了多个来源的Voc数据集时,可能会面临数据路径与名称无法对应的问题,需要对数据集进行融合,即对标注文件内容进行批量修改。
文件重命名
- 首先对每一个数据集的文件名称进行批量修改,请看脚本2批量修改文件名称(名称修改为顺序数字)
- 需要修改:文件路径以及文件扩展名称
- 注意:这只是对一个数据集进行批量命名,对于多个数据集,需要对起始顺序进行手动修改。
import os
import re
# 获取文件夹file_dir下指定类型file_type的所有文件名
def get_file_name(file_dir,file_type=''):#默认为文件夹下的所有文件
lst = []
for root, dirs, files in os.walk(file_dir):
for file in files:
if(file_type == ''):
lst.append(file)
else:
if os.path.splitext(file)[1] == str(file_type):#获取指定类型的文件名
lst.append(file)
return lst
file_dir = "C:/Users/MECHREVO/Desktop/test/"
files = get_file_name(file_dir)
- 由于返回的文件名列表并没有按照顺序存储在列表中,但我们的图像标注文件和图像文件必须是一一对应的,这就要求我们恢复原始的文件名顺序,下一步我们需要对返回的列表中的文件名称进行排序处理。
- 排序处理的思路很简单,将列表中的文件名称去除文件扩展名得到数字即可进行排序,通常我们使用labeling等图像标注软件生成的都是数字名称的数据集,如果读者需要实现自定义的比较,可以自定义富比较方法
# 获得文件数字并排序(可以看到上面是乱序)
import re
file_name_num = []
# 首先去掉文件扩展名
for each in files:
# 这一步是去掉.xml,也可以用replace
# 对于图片文件操作时,应改为对应的文件扩展名(如.jpg)
each_name_num = re.compile(r'.xml').sub(r'', each)
file_name_num.append(int(each_name_num))
# 对数字进行排序
file_name_num.sort()
- 对文件进行重新命名
# 设置文件名的起始顺序
i = -1
# 对文件名进行批量重命名
for name in files:# 遍历所有文件
i = i + 1
Olddir= file_dir + name
# 根据自己的需要对文件名称进行修改,生成新的文件名称
# 处理什么类型文件就填什么扩展名
Newdir= file_dir + str(i) + '.xml' # 对标注文件
# Newdir= file_dir + str(i) + '.jpg' # 对图片
# 重命名
os.rename(Olddir,Newdir)
对于每一个数据集的img和ann文件,我们都需要进行上述操作,并注意改变起始标号,比如:当处理第一个数据集时,我们设置起始标号为0,一直到完毕100,那么下一个数据集的标号就应该从101开始,继续往下标号。
最后将三个数据集的文件合并到一起(此时它们已经按顺序命名):
对xml文件的filename和path属性进行修改
- 对于voc数据集,模型是通过xml文件中的属性来索引其对应的img的,xml文件中是需要指定img文件的路径的,因此我们需要对xml文件中的filename、path属性进行修改。
- 需要修改:xml文件和img的存储位置
import os
import os.path
import xml.dom.minidom
path = "C:/Users/MECHREVO/Desktop/test/" #xml文件存储路径
#返回文件夹中的文件名列表
files=os.listdir(path)
#print(files)
- 修改filename
# 修改filename 此处是用阿拉伯数字递增命名
count=0
for xmlFile in files: