概述
本文是笔者的系列博文 《Bun技术评估》 中的第二十三篇。
在本文的内容中,笔者主要想要来探讨一下Bun中的Glob这个功能特性。
其实这个部分的内容,对于笔者而言其实也是一个新事物。相关的概念和应用方式,也是在逐步摸索当中。但之所以有本文,是因为在Bun技术文档中,有相关的章节,而且也是Bun内置的功能特性,让笔者觉得有必要了解一下。但这部分内容也不是特别重要,快速和初步了解即可。、
Glob
简单而言,Glob是一种基于通配符规则的文件名称匹配机制,它可以用于对文件列表进行过滤,方便进行筛选和后续操作。
Glob应该来源于类Unix系统Shell中的通配符展开(globbing),所以它的语法和规则,应当是和Shell是一致的。
关于这个功能特性的应用场景,笔者其实没有了解和体会的太多。但可以理解,肯定是和大量的文件操作有关。在实际Web应用开发中,很难想象这些场景,但好像对于前端应用的编译和打包,由于涉及大量文件操作,可能有一些应用的场景,这样就能够很好解释作为一个全合一的工具,Bun会内置这样的功能了。
示例和应用
我们先来看一下Bun中进行Glob操作的示例代码,有助于我们先建立基本概念和框架:
js
// 导入Glob模块
import { Glob } from "bun";
// 使用规则定义glob实例
const glob = new Glob("**/*.ts");
// Scan方法
// Scans the current working directory and each of its sub-directories recursively
for await (const file of glob.scan(".")) {
console.log(file); // => "index.ts"
}
// match方法
glob.match("index.ts"); // => true
glob.match("index.js"); // => false
上面的示例中,我们了解到Glob的设置和使用过程是非常简单的。就是基于匹配规则创建Glob实例,然后调用scan方法可以获取匹配规则的文件列表,或者使用match方法来判断特定文件是否满足匹配。
scan方法,有一个参数,是指开始扫描的路径。同时还提供了scanSync同步方法可以使用。
通配机制
显然,Glob的核心,其实是其匹配规则。它应当是和Unix系统是一致的,这里正好复习一下。常用的模式如下:
- ? 匹配单个字符
?用于单个字符的匹配规则。神奇的是,它支持中文
js
const glob = new Glob("???.ts");
glob.match("foo.ts"); // => true
glob.match("foobar.ts"); // => false
glob2.match("一二三.ts"); // true
- (*) 匹配0个或多个字符,但不支持"/"
js
const glob = new Glob("*.ts");
glob.match("index.ts"); // => true
glob.match("ax.ts"); // => true
glob.match("ax.js"); // => false
glob.match("src/index.ts"); // => false
- (**) 匹配任意多个字符,而且支持"/"
js
const glob = new Glob("**/*.ts");
glob.match("index.ts"); // => true
glob.match("src/index.ts"); // => true
glob.match("src/index.js"); // => false
-
ab\] 匹配列表中的单个字符,也支持\[0-9\],\[a-z\]等表示方法
const glob = new Glob("ba[rz].ts");
glob.match("bar.ts"); // => true
glob.match("baz.ts"); // => true
glob.match("bat.ts"); // => false
组合使用:
```js
const glob = new Glob("ba[a-z][0-9][^4-9].ts");
glob.match("bar01.ts"); // => true
glob.match("baz83.ts"); // => true
glob.match("bat22.ts"); // => true
glob.match("bat24.ts"); // => false ^4排除了4
glob.match("ba0a8.ts"); // => false 0不在a-z中间
- {a,b,c} 匹配其中一个字符
js
const glob = new Glob("{a,b,c}.ts");
glob.match("a.ts"); // => true
glob.match("c.ts"); // => true
glob.match("d.ts"); // => false
- ! 否定匹配
js
const glob = new Glob("!index.ts"); // 匹配不为index.ts的文件
glob.match("index.ts"); // => false
glob.match("foo.ts"); // => true
- \转义符
js
const glob = new Glob("\\!index.ts"); // 这里!就是真的文件名中的!了
glob.match("!index.ts"); // => true
glob.match("index.ts"); // => false
笔者感觉,基本上是结合了文件通配和简单的正则匹配规则。但考虑到可能涉及到后续的文件操作,Glob的应用不宜过于复杂。
类定义和选项
Glob在bun中的完整类定义如下,非常简单:
js
class Glob {
scan(root: string | ScanOptions): AsyncIterable<string>;
scanSync(root: string | ScanOptions): Iterable<string>;
match(path: string): boolean;
}
interface ScanOptions {
/**
* The root directory to start matching from. Defaults to `process.cwd()`
*/
cwd?: string;
/**
* Allow patterns to match entries that begin with a period (`.`).
*
* @default false
*/
dot?: boolean;
/**
* Return the absolute path for entries.
*
* @default false
*/
absolute?: boolean;
/**
* Indicates whether to traverse descendants of symbolic link directories.
*
* @default false
*/
followSymlinks?: boolean;
/**
* Throw an error when symbolic link is broken
*
* @default false
*/
throwErrorOnBrokenSymlink?: boolean;
/**
* Return only files.
*
* @default true
*/
onlyFiles?: boolean;
}
可以了解到,这里面还有一些比较实用的选项:
- onlyFiles?: 只匹配文件,排查链接、目录等等
- throwErrorOnBrokenSymlink?: 遇到中断的链接,抛出错误
- followSymlinks?: 跟随文件或文件夹链接
- absolute?: 返回绝对路径
- dot?: .开头,一般为隐形文件
- cmd: 搜索开始路径,默认process.cmd()
小结
笔者在本文中快速的浏览和探讨了Bun.Glob这个类和功能特性。了解到它其实是一种基于匹配规则获取文件列表和过滤的方式。文中展示了Glob的基本概念和由来,主要的使用方式,常见匹配规则定义和一些应用选项等等。