C#如何获取匹配含多层通配符路径规则的所有目录
问题原因
.NET 原生的Directory.GetDirectories/Directory.EnumerateDirectories方法不支持跨路径段的通配符匹配:
- 方法要求传入的基础路径必须是不含通配符的真实存在路径
- 通配符
*、?仅允许出现在最后一段搜索规则中,用于匹配当前层级的文件/文件夹 - 路径前缀中包含通配符时,系统会直接判定为非法路径名,抛出
System.IO.IOException,这就是两次代码运行报错的核心原因。
实现方案
方案1:无依赖原生递归实现
逐段解析路径规则,从固定根路径开始逐层匹配通配段,不需要引入第三方依赖,适配所有.NET版本:
using System.IO; using System.Collections.Generic; using System.Linq; public static IEnumerable<string> MatchDirectories(string pathPattern) { // 拆分路径为独立段,兼容正反斜杠分隔符 var segments = pathPattern.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) .Where(s => !string.IsNullOrEmpty(s)) .ToList(); // 初始化根路径(Windows下为盘符根目录,比如c:\) var currentDirs = new List<string> { segments[0] + Path.DirectorySeparatorChar }; for (int i = 1; i < segments.Count; i++) { var rule = segments[i]; var nextMatched = new List<string>(); foreach (var dir in currentDirs) { // 当前段无通配符,直接拼接路径校验存在性 if (!rule.Contains('*') && !rule.Contains('?')) { var target = Path.Combine(dir, rule); if (Directory.Exists(target)) nextMatched.Add(target); continue; } // 当前段含通配符,枚举当前层级所有匹配的子目录 nextMatched.AddRange(Directory.EnumerateDirectories(dir, rule)); } currentDirs = nextMatched; if (!currentDirs.Any()) break; } return currentDirs; }
调用方式:
var result = MatchDirectories(@"c:\logs\v*\api*").ToList();
运行后返回结果完全符合预期:
c:\logs\v1\api1 c:\logs\v1\api2 c:\logs\v2\api1 c:\logs\v2\api2
方案2:使用官方Glob匹配库
如果项目可以引入NuGet包,可以使用微软官方提供的Microsoft.Extensions.FileSystemGlobbing库,原生支持多级通配、**任意层级匹配等复杂规则,不需要自己实现递归逻辑:
- 先在项目中安装NuGet包:
Microsoft.Extensions.FileSystemGlobbing - 匹配目录代码如下:
using Microsoft.Extensions.FileSystemGlobbing; using Microsoft.Extensions.FileSystemGlobbing.Abstractions; var matcher = new Matcher(); // 添加匹配规则,注意规则中使用正斜杠作为路径分隔符 matcher.AddInclude("logs/v*/api*/*"); // 从c盘根目录开始执行匹配 var matchResult = matcher.Execute(new DirectoryInfoWrapper(new DirectoryInfo(@"c:\"))); // 提取匹配到的目录全路径 var result = matchResult.Files .Select(f => Directory.GetParent(Path.GetFullPath(Path.Combine(@"c:\", f.Path))).FullName) .Distinct() .ToList();
注意事项
- 不要尝试直接将多段带通配符的路径传入原生
Directory类的搜索方法,该类方法从设计上就不支持该场景 - 自定义递归实现时,推荐使用
EnumerateDirectories代替GetDirectories,前者是延迟枚举,大目录场景下内存占用更低。
内容的提问来源于stack exchange,提问作者dafie
相关产品推荐
相关产品推荐

