如何用 Bun Glob 扫描目录文件并匹配 glob 模式
【免费下载链接】bunIncredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one项目地址: https://gitcode.com/GitHub_Trending/bu/bun
如果你的任务是遍历一个目录找出符合条件的文件(例如项目里所有.ts文件),或者判断某个路径是否符合给定的通配规则,可以用 Bun 内置的原生 glob 实现Glob类完成:它对目录做的是真正的扫描(scan),对字符串做的是纯匹配(match),两者共用同一套 glob 模式语法。本文的前提是 Bun 已安装并可在PATH中找到(参见 安装文档),脚本用bun run运行即可,无需额外安装依赖。
完整 API 说明见 docs/runtime/glob.mdx,行为对应的测试在 test/js/bun/glob/scan.test.ts 和 test/js/bun/glob/match.test.ts。
准备条件
- Bun 已安装并在
PATH中(Quickstart 的前置要求)。 - 一个包含待扫描文件的目录。下文示例以当前工作目录
.作为扫描根目录。 - 新建一个 TypeScript 或 JavaScript 脚本文件,例如
scan.ts,用bun run scan.ts执行。
扫描目录文件
Glob的scan方法返回可迭代对象,逐条产出匹配到的路径;scanSync是同步版本。下面的示例递归扫描当前工作目录及其所有子目录,找出*.ts文件:
import { Glob } from "bun"; const glob = new Glob("**/*.ts"); // Scans the current working directory and each of its sub-directories recursively for await (const file of glob.scan(".")) { console.log(file); // 文档示例输出:如 "index.ts" }同步遍历改用scanSync,返回值为Iterable<string>:
import { Glob } from "bun"; const glob = new Glob("**/*.ts"); for (const file of glob.scanSync(".")) { console.log(file); }scan/scanSync的root参数可以传目录路径字符串,也可以传一个ScanOptions对象来控制扫描行为。文档给出的接口与选项如下,各选项的@default即默认值:
class Glob { scan(root: string | ScanOptions): AsyncIterable<string>; scanSync(root: string | ScanOptions): Iterable<string>; match(path: string): boolean; } interface ScanOptions { cwd?: string; // 扫描根目录,默认 process.cwd() dot?: boolean; // 是否允许匹配以 . 开头的条目,默认 false absolute?: boolean; // 是否返回绝对路径,默认 false followSymlinks?: boolean; // 是否遍历符号链接目录,默认 false throwErrorOnBrokenSymlink?: boolean; // 遇到断裂符号链接是否抛错,默认 false onlyFiles?: boolean; // 只返回文件,默认 true }几个常用组合:
// 只扫描指定目录,不递归进入符号链接目录 const glob = new Glob("**/*.ts"); for await (const file of glob.scan({ cwd: "./src" })) { console.log(file); } // 返回绝对路径 const glob2 = new Glob("**/*.js", { absolute: true }); for await (const file of glob2.scan(".")) { console.log(file); } // 默认只返回文件(onlyFiles 默认 true);要连目录一起列出,显式关掉它 const glob3 = new Glob("*", { onlyFiles: false }); for (const file of glob3.scanSync(".")) { console.log(file); }用 glob.match 匹配字符串
不在文件系统中扫描,而只是判断一个路径是否符合模式时,用match方法,返回boolean。文档给出的示例(返回值均为文档示例):
import { Glob } from "bun"; const glob = new Glob("*.ts"); glob.match("index.ts"); // => true glob.match("index.js"); // => falseBun 支持的 glob 模式及文档示例如下,可直接用于设计匹配规则:
?— 匹配任意单个字符
const glob = new Glob("???.ts"); glob.match("foo.ts"); // => true glob.match("foobar.ts"); // => false*— 匹配零个或多个字符,但不跨路径分隔符(/或\)
const glob = new Glob("*.ts"); glob.match("index.ts"); // => true glob.match("src/index.ts"); // => false**— 匹配任意数量的字符,包括/
const glob = new Glob("**/*.ts"); glob.match("index.ts"); // => true glob.match("src/index.ts"); // => true glob.match("src/index.js"); // => false[ab]— 匹配括号内的字符之一,也支持字符区间
const glob = new Glob("ba[rz].ts"); glob.match("bar.ts"); // => true glob.match("baz.ts"); // => true glob.match("bat.ts"); // => false区间写法如[0-9]、[a-z];否定写法^或!匹配括号内字符之外的一切([^ab]、[!a-z])。文档示例:
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 glob.match("ba0a8.ts"); // => false{a,b,c}— 匹配给定模式中的任意一个
const glob = new Glob("{a,b,c}.ts"); glob.match("a.ts"); // => true glob.match("b.ts"); // => true glob.match("c.ts"); // => true glob.match("d.ts"); // => false这类花括号模式最多可以嵌套 10 层,且内部可以包含前面介绍过的任意通配符。
!— 在模式开头取反结果
const glob = new Glob("!index.ts"); glob.match("index.ts"); // => false glob.match("foo.ts"); // => true\— 转义上述特殊字符
const glob = new Glob("\\!index.ts"); glob.match("!index.ts"); // => true glob.match("index.ts"); // => false这里"\\!index.ts"是 TypeScript 字符串字面量,实际模式是\!index.ts,匹配的文件名以字面!开头。
可选分支:Node.jsfs.glob()兼容写法
如果代码原本按 Node.js 的fs.glob()编写,Bun 也实现了这组函数,可以不改写法直接使用。第一参数支持传入模式数组,选项支持exclude过滤结果:
import { glob, globSync, promises } from "node:fs"; // Array of patterns const files = await Array.fromAsync(promises.glob(["**/*.ts", "**/*.js"])); // Exclude patterns const filtered = await Array.fromAsync( promises.glob("**/*", { exclude: ["node_modules/**", "**/*.test.*"], }), );文档说明fs.glob()、fs.globSync()、fs.promises.glob()三个函数都支持:第一参数传模式数组;exclude选项过滤结果。这条路径适合把 Node 项目里的 glob 调用平移到 Bun 环境。
运行与验证
在一个包含若干.ts文件的目录中,把上面「扫描目录文件」一节的示例存为scan.ts,然后执行:
bun run scan.ts预期现象以当前目录实际存在的文件为准:脚本会逐行打印匹配到的路径。文档 Quickstart 中给出的console.log(file); // => "index.ts"是文档示例输出,表示工作目录下存在index.ts时的单行打印效果,不是固定预期结果。
判断匹配规则是否生效,用match断言最直观:对同一模式分别传入应命中与不应命中的路径,返回true/false与文档示例一致即说明模式写对了(例如*.ts对index.ts返回true,对index.js返回false)。
限制与边界
dot默认false:以.开头的条目默认不会匹配,需要时显式传dot: true。onlyFiles默认true:scan默认只返回文件,不返回目录。followSymlinks默认false:不会遍历符号链接指向的子目录;throwErrorOnBrokenSymlink默认false,遇到断裂符号链接不抛错,需要抛错时显式开启。cwd默认process.cwd():不传ScanOptions时扫描根目录就是进程当前工作目录。- 花括号模式
{a,b,c}嵌套上限为 10 层。 !取反只作用于模式开头;*不跨路径分隔符,跨目录递归必须用**。
如果项目里需要把 glob 用于测试文件的并行分组等场景,可参考 docs/guides/test/concurrent-test-glob.mdx 中的 glob 用法说明。
【免费下载链接】bunIncredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one项目地址: https://gitcode.com/GitHub_Trending/bu/bun
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考