C#递归搜索指定目录下的文件或目录

诚然可以使用现成的Directory类下的GetFiles、GetDirectories、GetFileSystemEntries这几个方法实现同样的功能,但请相信我不是蛋疼,原因是这几个方法在遇上【System Volume Information】这种目录时,极有可能会给你个拒绝访问的异常,想跳过都不行。所以没办法,重新实现了一下。

实现说明

- 仍然是基于对Directory类的几个方法的封装进行实现,只是没有使用它们的searchPattern和searchOption功能
- 将匹配模式由windows的通配符?、*改为正则匹配。一是让匹配更强大,二是要实现?*匹配还得做额外工作,没必要
  匹配模式并没有默认添加首尾限定^$,即“abc"将会匹配所有包含该字串的项目,所以如果你要匹配首尾,请自行添加^$
  忽略大小写匹配
  如果不想搜索指定项目而是全部,请将regexPattern参数设为null,而不是.*,前者性能更好
- 可通过设置recurse和throwEx参数决定是否递归搜索,和是否抛异常。默认是不递归,不抛异常
- 遇到不可访问的目录会跳过。当然前提是throwEx=false
- 之所以在foreach外层再套一层try-catch,是因为如果指定的dir就是不可访问的目录,那也可以避免异常
- 之所以为获取项、获取文件、获取目录分别实现3个方法,而不是只实现一个获取项,另外两个重载,是因为只实现一个的话,foreach中要做的逻辑判断不少,考虑到方法是要递归的,所以循环中逻辑越少越好
- 之所以不做dir参数合法性检查,原因同上,判断越少越好。所以请用户调用前自行确保dir合法

不废话,上代码:
复制代码
/// <summary>
/// 获取指定目录中的匹配项(文件或目录)
/// </summary>
/// <param name="dir">要搜索的目录</param>
/// <param name="regexPattern">项名模式(正则)。null表示忽略模式匹配,返回所有项</param>
/// <param name="recurse">是否搜索子目录</param>
/// <param name="throwEx">是否抛异常</param>
/// <returns></returns>
private static string[] GetFileSystemEntries(string dir, string regexPattern = null, bool recurse = false, bool throwEx = false)
{
    List<string> lst = new List<string>();

    try
    {
        foreach (string item in Directory.GetFileSystemEntries(dir))
        {
            try
            {
                if (regexPattern == null || Regex.IsMatch(Path.GetFileName(item), regexPattern, RegexOptions.IgnoreCase | RegexOptions.Multiline))
                { lst.Add(item); }

                //递归
                if (recurse && (File.GetAttributes(item) & FileAttributes.Directory) == FileAttributes.Directory)
                { lst.AddRange(GetFileSystemEntries(item, regexPattern, true)); }
            }
            catch { if (throwEx) { throw; } }
        }
    }
    catch { if (throwEx) { throw; } }

    return lst.ToArray();
}

/// <summary>
/// 获取指定目录中的匹配文件
/// </summary>
/// <param name="dir">要搜索的目录</param>
/// <param name="regexPattern">文件名模式(正则)。null表示忽略模式匹配,返回所有文件</param>
/// <param name="recurse">是否搜索子目录</param>
/// <param name="throwEx">是否抛异常</param>
/// <returns></returns>
private static string[] GetFiles(string dir, string regexPattern = null, bool recurse = false, bool throwEx = false)
{
    List<string> lst = new List<string>();

    try
    {
        foreach (string item in Directory.GetFileSystemEntries(dir))
        {
            try
            {
                bool isFile = (File.GetAttributes(item) & FileAttributes.Directory) != FileAttributes.Directory;

                if (isFile && (regexPattern == null || Regex.IsMatch(Path.GetFileName(item), regexPattern, RegexOptions.IgnoreCase | RegexOptions.Multiline)))
                { lst.Add(item); }

                //递归
                if (recurse && !isFile) { lst.AddRange(GetFiles(item, regexPattern, true)); }
            }
            catch { if (throwEx) { throw; } }
        }
    }
    catch { if (throwEx) { throw; } }

    return lst.ToArray();
}

/// <summary>
/// 获取指定目录中的匹配目录
/// </summary>
/// <param name="dir">要搜索的目录</param>
/// <param name="regexPattern">目录名模式(正则)。null表示忽略模式匹配,返回所有目录</param>
/// <param name="recurse">是否搜索子目录</param>
/// <param name="throwEx">是否抛异常</param>
/// <returns></returns>
private static string[] GetDirectories(string dir, string regexPattern = null, bool recurse = false, bool throwEx = false)
{
    List<string> lst = new List<string>();

    try
    {
        foreach (string item in Directory.GetDirectories(dir))
        {
            try
            {
                if (regexPattern == null || Regex.IsMatch(Path.GetFileName(item), regexPattern, RegexOptions.IgnoreCase | RegexOptions.Multiline))
                { lst.Add(item); }

                //递归
                if (recurse) { lst.AddRange(GetDirectories(item, regexPattern, true)); }
            }
            catch { if (throwEx) { throw; } }
        }
    }
    catch { if (throwEx) { throw; } }

    return lst.ToArray();
}
复制代码

 

posted @   Mr. Hu  阅读(4496)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
Map
点击右上角即可分享
微信分享提示
+

"感谢您的支持,我会继续努力"

微信支付
支付宝支付