【问题标题】:List all folders which match defined path pattern列出与定义的路径模式匹配的所有文件夹
【发布时间】:2010-12-11 17:35:40
【问题描述】:

我需要对文件共享中与定义的模式匹配的所有文件夹执行一些操作。模式可以指树中的多个级别,例如 \Test\[a-z]+\Project[0-9]{3}

遍历树以查找所有匹配文件夹的最有效方法是什么?有没有比使用 DirectoryInfo 和 di.GetDirectories() 进行简单的递归深度优先搜索更好的方法,例如:

private void TraverseSubFolder(DirectoryInfo folder)
{
    if (filter.IsMatch(folder.FullName)) {
       DoStuff(folder);
    }

    DirectoryInfo[] subFolders = folder.GetDirectories();
    foreach (DirectoryInfo sf in subFolders)
    {
        TraverseSubFolder(sf);
    }
}

【问题讨论】:

    标签: .net


    【解决方案1】:

    你可以使用 Linq 来过滤

    Regex regex = new Regex("your regex");
    var directories = Directory.GetDirectories("c:\\", null, SearchOption.AllDirectories).Where(directory => regex.IsMatch(directory));
    

    这种方法的缺点是它仍然会搜索被过滤掉的不需要的文件夹,因为Where发生在所有文件夹都返回之后。

    这可以调整。

    编辑

    这不适用于 SearchOption.AllDirectories,因为一旦您点击了您无权的文件夹,就会抛出 UnauthorizedAccessException。

    由于检查了 UnauthorizedAccessException,我认为您不能没有递归函数。

    我使用 Linq 对这种方法进行了编码,但它与您自己的方法并没有太大区别。至少它检查许可。它仍然容易出现 StackOverflowException。

    private static void Traverse(List<string> folders, string rootFolder, Regex filter)
    {
        try
        {
            // Test for UnauthorizedAccessException
            new FileIOPermission(FileIOPermissionAccess.PathDiscovery, rootFolder).Demand();
    
            Array.ForEach(Directory.GetDirectories(rootFolder),
                (directory) =>
                {
                    if (filter.IsMatch(directory))
                    {
                        folders.Add(directory);
    
                        Traverse(folders, directory, filter);
                    }
                });
        }
        catch 
        {
            // Ignore folder that we don't have access to
        }
    }
    
    // Usage example
    List<string> folders = new List<string>();
    Regex regex = new Regex("^.+$");
    Traverse(folders, "e:\\projects", regex);
    

    【讨论】:

    • 这实际上似乎比我的递归搜索慢一点(尽管它肯定更优雅)。有没有办法处理未经授权的访问异常?
    • 是的,它会更慢,因为它会遍历不应该去的地方,因为过滤器发生在整个遍历之后。至于访问异常,我虽然 GetDirectories 正在处理它。诡异的。我想您可以使用 Reflector 检查 GetDirectories。
    • 感谢您的编辑 - 这是非常方便的信息。我在大约 5500 个文件夹的树上运行了一些快速测试(由于未经授权的访问异常,无法尝试更多),我的递归 DirectoryInfo 调用的时间为 2.10 秒,使用 LINQ 过滤器的原始 GetDirectories 过程为 3.50 和 4.47对于@Nestor 的方法和后续的正则表达式模式匹配。我的递归方法仍然会进入不匹配的文件夹,因为即使他们的父母不匹配,孩子也可能匹配,所以这并不能向我解释时间差异..
    【解决方案2】:

    Directory.GetDirectories(..,.., SearchOption.AllDirectories)

    【讨论】:

    • 那不行,他正在尝试在完整路径上进行模式匹配
    • 搜索模式参数是否支持具有多级文件夹的模式(如我的问题中的模式)?例如,它似乎不支持正则表达式模式,除了 . 等之外,我在网上找不到任何好的示例。
    • 返回的文件将是完整路径。所以你可以对它们应用你的正则表达式。
    猜你喜欢
    • 2012-05-08
    • 2014-11-02
    • 2018-05-15
    • 1970-01-01
    • 2012-01-21
    • 1970-01-01
    • 1970-01-01
    • 2012-09-19
    相关资源
    最近更新 更多