【问题标题】:Multiple wildcard directory/file search for arbitrary directory structure in C# .net多个通配符目录/文件在 C# .net 中搜索任意目录结构
【发布时间】:2016-08-13 16:15:48
【问题描述】:

我正在使用 C# 和 .net 4.0 在 Visual Studio 2012 中构建 Windows 应用程序。

该程序的功能之一是搜索满足给定搜索条件的所有文件,这些条件通常(但不总是)包括通配符。

搜索条件在运行时未知;它是从 Excel 电子表格导入的。

可能的搜索条件可以包括以下内容:

  1. 准确路径
    • “C:\temp\directory1\directory2\someFile.txt”
  2. 路径,文件名中带有通配符:
    • "C:\temp\directory1\directory2*.*"
  3. 文件名,路径中带有通配符:
    • "C:\temp*\directory*\someFile.txt"
  4. 带有通配符的文件名和路径:
    • “C:\temp\*\*\*.*”
  5. 以上所有,具有任意目录结构:
    • "C:\temp\dir*1\dir*\anotherdir\*\another*\file*.txt"
    • “C:\te*\*\someFile.txt”
    • “C:\temp\*tory1\dire*2\*\*\*\*\*.*”

我尝试使用Directory.EnumerateFiles:

IEnumerable<string> matchingFilePaths = System.IO.Directory.EnumerateFiles(@"C:\", selectedItemPath[0], System.IO.SearchOption.AllDirectories);

但这仅适用于上述情况 2。尝试在文件夹名称中使用带有通配符的 Directory.EnumerateFiles 会导致“非法字符”豁免。

我希望 .net 中有一个单行代码可以用来进行文件搜索。通配符的数量和目录结构的深度在运行时是未知的,并且可以想象搜索可能必须深入一百个文件夹,每个文件夹都包含未知数量的通配符。 (这是问题的症结所在)。尽量避免嵌套的 for 循环数量过多。

我阅读了here 的解决方案,但这似乎不适用于任意文件夹结构。

【问题讨论】:

  • 恐怕 .net 有满足您要求的 API。你必须自己写。
  • 很明显,您引用的问题有一个让您开始的地方,如果您想自己做这件事,那么您当然可以使用它作为参考。您是否要求我们不费吹灰之力地为您完成这项工作?

标签: c# .net search directory


【解决方案1】:

既然您已经回答了自己的问题,我想我会将我的尝试发布给任何可能发现此问题并且不想使用 powershell 的其他人。它都是延迟加载的,因此在您拥有大型文件系统并匹配大量文件的情况下,它的性能将是最佳的。

示例用法:

string pattern = @"C:\Users\*\Source\Repos\*\*.cs";
foreach (var st in GetAllMatchingPaths(pattern))
    Console.WriteLine(st);

解决方案:

public static IEnumerable<string> GetAllMatchingPaths(string pattern)
{
    char separator = Path.DirectorySeparatorChar;
    string[] parts = pattern.Split(separator);

    if (parts[0].Contains('*') || parts[0].Contains('?'))
        throw new ArgumentException("path root must not have a wildcard", nameof(parts));

    return GetAllMatchingPathsInternal(String.Join(separator.ToString(), parts.Skip(1)), parts[0]);
}

private static IEnumerable<string> GetAllMatchingPathsInternal(string pattern, string root)
{
    char separator = Path.DirectorySeparatorChar;
    string[] parts = pattern.Split(separator);

    for (int i = 0; i < parts.Length; i++)
    {
        // if this part of the path is a wildcard that needs expanding
        if (parts[i].Contains('*') || parts[i].Contains('?'))
        {
            // create an absolute path up to the current wildcard and check if it exists
            var combined = root + separator + String.Join(separator.ToString(), parts.Take(i));
            if (!Directory.Exists(combined))
                return new string[0];

            if (i == parts.Length - 1) // if this is the end of the path (a file name)
            {
                return Directory.EnumerateFiles(combined, parts[i], SearchOption.TopDirectoryOnly);
            }
            else // if this is in the middle of the path (a directory name)
            {
                var directories = Directory.EnumerateDirectories(combined, parts[i], SearchOption.TopDirectoryOnly);
                var paths = directories.SelectMany(dir =>
                    GetAllMatchingPathsInternal(String.Join(separator.ToString(), parts.Skip(i + 1)), dir));
                return paths;
            }
        }
    }

    // if pattern ends in an absolute path with no wildcards in the filename
    var absolute = root + separator + String.Join(separator.ToString(), parts);
    if (File.Exists(absolute))
        return new[] { absolute };

    return new string[0];
}

PS:它不会匹配目录,只匹配文件,但如果需要,您可以轻松修改。

【讨论】:

  • 感谢您的解决方案!我希望避免任何复杂的事情,我认为我的 PowerShell 方法应该可以工作,但如果我发现它不起作用的情况,我会使用你的解决方案。
【解决方案2】:

经过更多搜索,结果发现有一个非常简单的解决方案。我可以使用 Windows Powershell Get-ChildItem 命令:

using System.Management.Automation;

PowerShell ps = PowerShell.Create();
ps.AddCommand("Get-ChildItem");
ps.AddArgument(selectedItemPath[0]);
foreach (var result in ps.Invoke())
{
    //display the results in a textbox
}

这可以避免嵌套的for 循环。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-29
    • 1970-01-01
    • 2013-12-24
    相关资源
    最近更新 更多