前言
获取目录下匹配某种规则的文件,返回文件列表,在开发中比较常用。本文实现此功能,并做了些扩展。
起因
笔者开发的内部工具,需要查找各式文件,比如:
- 数据文件,以csv结尾;
- 信息文件,以md结尾(因为已有工具生成并渲染得html发布到网页上,直接拿来使用);
- 压缩包,以zip结尾。
由于设计原因,部分不同各类的文件会在同一目录出现,因此,要实现一个接口用以获取某个目录下符合条件的文件。
设计思路如下:
- 为简单化,不递归查找子目录,当传入的非目录或不存在时,直接返回即可。
- 设计是否带目录标志,有时仅需文件名称,而不需要其目录。
- 设计返回文件列表数量,0表示所有文件,因此有时仅需要得到符合要求的第一个文件。
- 设计是否排序标志,因为默认是升序,所以该标志实际是降序标志。
实现
为减少篇幅,仅摘录必要的源码。
patten
- GetFileListBySuffix:patten 作为后缀,可按后缀名匹配。通过strings.HasSuffix判断。
- GetFileListByPrefix:同前,但是是前缀。通过strings.HasSuffix判断。
- GetFileListByKey:同上,在任意位置出现均可。通过strings.HasPrefix判断。
os.FileInfostrings.Contains
封装
代码如下:
测试及结果
测试用到的目录及文件如下:
$ tree foo/
foo/
|-- bar_1.json
|-- bar_10.json
|-- bar_2.json
|-- bar_20.json
|-- bar_3.json
|-- log.1
|-- log.10
|-- log.2
|-- log.20
`-- log.30 directories, 10 files
前缀匹配调用:
结果:
[foo\log.1 foo\log.10 foo\log.2 foo\log.20 foo\log.3] <nil>
后缀匹配调用:
结果:
[foo\bar_1.json foo\bar_10.json foo\bar_2.json foo\bar_20.json foo\bar_3.json] <nil>
一般匹配调用:
结果:
[foo\bar_1.json foo\bar_10.json foo\log.1 foo\log.10] <nil>
从结果分析,符合预期。
扩展
优化接口
从前面封装的接口代码分析,绝大部分代码是相同的,仅仅是读取后对文件名称的判断不同而已。因此,可以将它们合成一个接口。设计如下:
patten**foo**foo*foo**
代码如下:
调用如下:
结果如下:
[foo\log.1 foo\log.10 foo\log.2 foo\log.20 foo\log.3] <nil>
[foo\bar_1.json foo\bar_10.json foo\bar_2.json foo\bar_20.json foo\bar_3.json] <nil>
[foo\bar_1.json foo\bar_10.json foo\log.1 foo\log.10] <nil>
正则表达式
虽然目前未使用到,但还是实现了按正则表达式来匹配文件名的接口,实现如下:
调用如下:
结果如下:
log.+ : [foo\log.1 foo\log.10 foo\log.2 foo\log.20 foo\log.3] <nil>
[a-z0-9_]*.json : [foo\bar_1.json foo\bar_10.json foo\bar_2.json foo\bar_20.json foo\bar_3.json] <nil>
说明:正则表达式一定要符合要求,否则不识别。
带数字的文件名称排序
前面的测试结果:
[foo\log.1 foo\log.10 foo\log.2 foo\log.20 foo\log.3]
os.FileInfoLess
因为带数字的文件名称有各式各样,此处假定按文件的“后缀名”数字由大到小排序。实际上,这是真实的的场合:某工程程序产生的日志,按超过指定大小会自动创建新的文件,后缀带数字即表达有多少个日志文件。
代码如下:
调用如下:
结果如下:
sort number : [foo\log.20 foo\log.10 foo\log.3 foo\log.2 foo\log.1] <nil>
从结果看,已实现根据数字从大到小排序。
总结
文中所实现的接口,已应用到笔者实际的工程。目前未发现有什么问题。
隔了一天的PS:
由于传递参数可以指定文件数量,当指定的数量多了实际数量时,会报错,需要加上判断。在“优化接口”及后面小节的代码中已修正,前面由于实际中不使用,故保留。
有时话真的不是说得太满。记之并以此为鉴。