C#中高效按父目录分组排序,实现保留过期父目录下最新符合模式子目录的方法
解决方案:按父目录分组筛选,保留每组最新过期目录
你的思路完全正确——按父目录分组后再处理就是解决这个需求的最优路径。我们可以通过组合LINQ的分组、筛选和排序操作,高效实现“同一父目录下若所有符合模式的子目录都过期,仅保留最新的一个”的逻辑,同时兼顾性能。
核心思路拆解
- 精准获取目标目录信息:直接用
DirectoryInfo获取目录的元数据(创建时间、父目录等),避免重复IO操作; - 按父目录分组:将所有
*_select目录按它们的父目录路径分组,确保同一父目录下的目录被归为一组; - 分情况处理每组:
- 如果组内有未超过30天的目录:所有过期目录直接标记删除;
- 如果组内所有目录都已过期:仅保留创建时间最新的那个,其余标记删除;
- 批量执行删除:最后统一处理标记的目录,减少零散操作的开销。
完整代码实现
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; class Program { // 预编译正则表达式,提升多次匹配的效率 private static readonly Regex SelectDirRegex = new Regex(@"_select$", RegexOptions.Compiled); static void Main(string[] args) { string rootPath = @"C:\Main"; var thirtyDaysAgo = DateTime.Now.AddDays(-30); // 1. 获取所有符合模式的目录信息 var patternDirInfos = new DirectoryInfo(rootPath) .GetDirectories("*", SearchOption.AllDirectories) .Where(dir => SelectDirRegex.IsMatch(dir.Name)) // 仅匹配目录名结尾为_select的 .ToList(); if (!patternDirInfos.Any()) { Console.WriteLine("未找到符合模式的目录"); return; } // 2. 按父目录路径分组 var groupedDirs = patternDirInfos.GroupBy(dir => dir.Parent.FullName); // 3. 筛选出需要删除的目录 var dirsToDelete = new List<DirectoryInfo>(); foreach (var group in groupedDirs) { var activeDirs = group.Where(dir => dir.CreationTime > thirtyDaysAgo).ToList(); var expiredDirs = group.Where(dir => dir.CreationTime <= thirtyDaysAgo).ToList(); if (activeDirs.Any()) { // 组内有未过期目录,所有过期目录都删除 dirsToDelete.AddRange(expiredDirs); } else { // 组内所有目录都过期,仅保留最新的一个 var sortedExpired = expiredDirs.OrderByDescending(dir => dir.CreationTime).ToList(); dirsToDelete.AddRange(sortedExpired.Skip(1)); } } // 4. 执行删除操作(添加异常处理避免程序崩溃) foreach (var dir in dirsToDelete) { try { dir.Delete(true); // true表示递归删除所有子目录和文件 Console.WriteLine($"成功删除目录:{dir.FullName}"); } catch (IOException ex) { Console.WriteLine($"删除目录失败(IO异常):{dir.FullName},原因:{ex.Message}"); } catch (UnauthorizedAccessException ex) { Console.WriteLine($"删除目录失败(权限不足):{dir.FullName},原因:{ex.Message}"); } } } }
性能优化说明
- 预编译正则表达式:避免每次匹配都重新编译正则,提升多次调用的效率;
- 直接使用DirectoryInfo:一次性获取目录的所有元数据,无需后续再调用
new DirectoryInfo(),减少IO开销; - 分组内排序而非全局排序:仅对每个父目录下的少量目录排序,而非所有目录全局排序,数据量越大优势越明显;
- 批量处理删除:集中处理删除操作,减少系统调用次数。
额外注意事项
- 时区问题:如果你的服务器使用UTC时间,建议改用
DateTime.UtcNow.AddDays(-30),避免本地时区转换导致的判断误差; - 权限问题:确保程序有足够的权限删除目标目录及其内容;
- 异常处理:添加针对性的异常捕获(如IO异常、权限异常),避免单个目录删除失败导致整个程序终止。
内容的提问来源于stack exchange,提问作者Erelephant
相关产品推荐
相关产品推荐

