批处理文件实战(二) 文件分类与管理

背景

今天在朋友圈看见一同学遇见这样问题:她拿到了一大堆由程序自动生成的高度格式化的数据。数据为ASCII编码的纯文本文件。文本中记录了一些信息,其中有且仅有一行文本定义了数据类型。她的任务是将所有的文本文件按照不同的数据类型定义进行分类,并且将相同数据类型的文本文件放入相同的文件夹中。这种工作听起来就很无趣而且很容易造成疲劳。令人抓狂的是,眼前有GB级的数据等待处理。

在日常工作中,很可能会经常性的遇到这样的数据炸弹要处理。从很多程序导出的数据都有这样的特点,即遵循特定的规则排列,有工整的组织结构。很多日志文件都是按照日期格式存储的。例如我近期接触的B787飞机的日志文件是按照时间记录,记录方式为纯文本日志文件。一些FTP日志文件也是以日期为单位记入日志文件。所谓日志,不就是每日来一志么?

如果哪天领导上级对某一项数据感兴趣,底下的人就惨了。例如,刚刚提及的787的日志文件中包含一个叫做Maintenance Message(MM)的东西,属于故障代码的一种。也许有一天,航空公司的领导突然想统计一下各种MM发生的分布情况,那就只能查阅日志咯。这种苦逼的事情肯定要轮到机务部门身上的。这种工作交给程序员分分钟就解决了,可是程序员不去当机务员啊。哎!

任务描述

tree

言归正传。上面的图是此次工作路径的目录树的示意图。其中红色部分是待处理的目标文件,扩展名均为tsm。处理之前,蓝色的目录树不存在,需要在处理数据过程中建立。经过处理后,红色区域内的文件会被移动到蓝色区域对应的文件夹中。

图中表示只是单个工作目标的目录树,整个任务要求处理数百个这样的目录。因此,我们选择的工作路径是subroot的父文件夹。

文档数据说明

文档数据样本如下

QU CANXMCZ
.QXSXMXS 250725
MAS
AN B-5283/FI CZ3027/MA 657S
DT QXS LKO1 250725 S22A



文档中标记类型的数据以ASCII控制符STX(意思是start of text)开始,后面跟着数据类型的定义。样本文件中的数据类型为“MAS”。在每份文档中都有且只有唯一一个这个的控制符。因此实现分类的策略就是查找带有“STX”控制符的这一行,进而通过这行数据获取数据类型。

上述提到的数据类型共有48个。

批处理文件实现

@echo off & setlocal enabledelayedexpansion
set list=CFD REJ FML AFD JRF MED FM3 M16 M10 M11 CDA RAI M13 PAR MAS M27 M45 RCD M46 FMR M15 ENG TT6 A81 M23 JDL M12 A83 TT1 M21 M22 A8X M1L M17 M14 M49 TT5 HJK M48 DFD WXR M47 A80 JLS SVC ATC M24 M25
for /f "delims=" %%l in ('dir /b /ad') do (
	cd %%l
	for %%i in (%list%) do mkdir %%i
	for /r %%j in (*.tsm) do (
	for /f "skip=2 delims=" %%k in ('find "" %%j') do (
			set type=%%k
			rem echo %%~nxj is of type !type:~-3!
			>nul move %%j !type:~-3!
		)
	)
	cd ..
)
pause

命令解释

博客批处理文件实战(一)已经解释部分命令的作用,这里只陈述未说明的部分。

首先是第2行。上文提到数据类型有48个,为了方便,将其放入变量list中,数据类型以空格隔开。

第3行已不陌生。与之前不同的一点是dir命令多了一个选项“/ad”,表示只列举目录列表。

cd命令(change directory)用于改变工作目录。这里,我们通过for和cd命令的组合来遍历进入根目录下的所有子文件夹。

mkdir命令用于创建文件夹,别名md。通过这行命令,就可以创建图中蓝色区域的目录树。

语句

for /r %%variable in (set)

非常的强大,它的作用是以当前目录为根节点,穷举整个目录树。通过这种方式,就可以找到当前文件夹下的所有tsm文件。

又一次见到了for语句。这一“option”中添加了“skip=2”,后面的集合中的一行数据。在进行查找、按行读取数据时经常会用到这个功能。使用纯文本存储数据时,经常都会在第一行写个注释或者是其他信息,在解析数据时没有作用,需要跳过。

find实现查找功能。最简单的用法为

find "string" filename

find输出查找到的行。还有一个与find类似的命令findstr,支持模式查找,具体信息见

find /? & findstr /?

以rem开头的行是注释,不执行。如果去除注释,第9航的作用是打印文件的数据类型。for变量中插入“~nx”表示将变量扩展成“文件名+扩展名”。这一行中!type:~-3!表示截取变量type的后三个字符。更一般的表达式为

%variable:~m,n%

(之前已经说明%和!的区别)其中m为偏移的字符数,n为长度。

下一行开头的“>nul”作用为消除move命令的结果显示。其中“<”是重定向符,“nul”可以理解为黑洞。最后mv命令简单易懂,后面跟的两个参数分别为要移动的文件路径和目标路径

“cd ..”表示返回上级目录。

未经允许不得转载:Charlie小站 » 批处理文件实战(二) 文件分类与管理

赞 (4)
分享到:更多 ()