如何使用VS Code findFiles实现类globby的多Glob模式匹配功能
VS Code findFiles 多Glob模式匹配解决方案
接口背景
VS Code扩展运行在Node环境下,常规Node fs模块只能访问扩展运行时所在的本地文件系统,无法适配Docker、WSL等远程文件系统场景。VS Code官方提供的vscode.workspace.findFiles接口基于Uri实现,原生支持各类远程文件系统访问,接口定义如下:
findFiles( include: GlobPattern, exclude?: GlobPattern | null, maxResults?: number, token?: CancellationToken ): Thenable<Uri[]>
该接口为类globby的Glob匹配能力,但存在两个使用限制:
- 仅支持传入单个Glob模式作为include参数,不支持globby风格的模式数组
- 拼接多模式使用的大括号语法不支持嵌套,若原有模式已包含大括号(如
**/*.{exe,dll,pdb,hex,bin}),嵌套拼接后规则会失效
无嵌套展开的实现方案
以下两种方案均不需要手动编写正则展开嵌套Glob规则,可实现和globby一致的多模式匹配效果:
方案1:并行调用+结果去重
对每个Glob模式单独调用findFiles接口,最后合并结果并按Uri去重即可,实现逻辑最简单:
import * as vscode from 'vscode'; async function findFilesWithPatterns( includePatterns: string[], excludePattern?: vscode.GlobPattern | null, maxResultsPerPattern?: number, token?: vscode.CancellationToken ): Promise<vscode.Uri[]> { // 并行执行所有模式的查找请求 const resultGroups = await Promise.all( includePatterns.map(pattern => vscode.workspace.findFiles(pattern, excludePattern, maxResultsPerPattern, token) ) ); // 结果去重避免不同模式匹配到同一文件 const uriCache = new Set<string>(); const uniqueResults: vscode.Uri[] = []; for (const uri of resultGroups.flat()) { const uriString = uri.toString(); if (!uriCache.has(uriString)) { uriCache.add(uriString); uniqueResults.push(uri); } } return uniqueResults; }
该方案完全复用findFiles的远程适配能力,无兼容性问题,并行调用的性能开销在绝大多数场景下可以忽略。
方案2:单通查询+后置过滤
如果需要控制findFiles的调用次数,可以先用粗粒度规则拉取文件列表,再用成熟的Glob匹配库做后置过滤,天然支持嵌套大括号和多模式匹配:
import * as vscode from 'vscode'; import { minimatch } from 'minimatch'; async function findFilesWithPatterns( includePatterns: string[], excludePattern?: vscode.GlobPattern | null, maxResults?: number, token?: vscode.CancellationToken ): Promise<vscode.Uri[]> { // 拉取全量文件,也可自定义粗过滤规则缩小查询范围 const allCandidateFiles = await vscode.workspace.findFiles('**/*', excludePattern, undefined, token); const matchedResults: vscode.Uri[] = []; for (const uri of allCandidateFiles) { // 匹配任意一个include模式即可保留 const isMatch = includePatterns.some(pattern => minimatch(uri.fsPath, pattern)); if (isMatch) { matchedResults.push(uri); if (maxResults && matchedResults.length >= maxResults) { break; } } } return matchedResults; }
该方案仅调用一次findFiles接口,匹配逻辑和globby完全一致,适合工作区文件量不大的场景使用。
内容的提问来源于stack exchange,提问作者Peter Wone
相关产品推荐
相关产品推荐

