用0.15.2破解GetFiles中的更改可以';t排除文件夹

本文关键字:文件夹 排除 破解 GetFiles | 更新日期: 2023-09-27 18:01:04

我记不清在哪里了,但找到了一个如何将文件夹排除在搜索之外的示例。我们的问题是搜索node_modules会导致长路径异常。

Func<IFileSystemInfo, bool> exclude_node_modules = fileSystemInfo=>!fileSystemInfo.Path.FullPath.Contains("node_modules");
var solutions = GetFiles("./**/*.sln", exclude_node_modules);

解决这个问题的任何帮助都是有帮助的。

用0.15.2破解GetFiles中的更改可以';t排除文件夹

为了加快文件系统的递归遍历,Cake利用.NET内置功能来实现这一点,但它受到Windows旧的260个字符限制。因此,当它在大多数用例中速度快一个量级时,它会在太深的文件夹结构上失败,比如节点模块可能会引入。

您可以通过逐个文件夹迭代并在输入之前对要排除的文件夹应用谓词来解决此问题。

在我的例子中,下面的文件夹结构使用

Repo directory
    |   build.cake
    |   test.sln
    |
    '---src
        |   test.sln
        |
        +---proj1
        |   |   test.sln
        |   |
        |   '---node_modules
        |           node.sln
        |
        +---proj2
        |   |   test.sln
        |   |
        |   '---node_modules
        |           node.sln
        |
        +---proj3
        |   |   test.sln
        |   |
        |   '---node_modules
        |           node.sln
        |
        '---proj4
            |   test.sln
            |
            '---node_modules
                    node.sln

我们想要的是从repo目录递归地找到所有解决方案,不进入node_modules目录,也不找到node.sln

以下建议的解决方案是创建一个名为RecursiveGetFile的实用程序方法,为您做到这一点:

// find and iterate all solution files
foreach(var filePath in RecursiveGetFile(
    Context,
    "./",
    "*.sln",
    path=>!path.EndsWith("node_modules", StringComparison.OrdinalIgnoreCase)
    ))
{
    Information("{0}", filePath);
}

// Utility method to recursively find files
public static IEnumerable<FilePath> RecursiveGetFile(
    ICakeContext context,
    DirectoryPath directoryPath,
    string filter,
    Func<string, bool> predicate
    )
{
    var directory = context.FileSystem.GetDirectory(context.MakeAbsolute(directoryPath));
    foreach(var file in directory.GetFiles(filter, SearchScope.Current))
    {
        yield return file.Path;
    }
    foreach(var file in directory.GetDirectories("*.*", SearchScope.Current)
        .Where(dir=>predicate(dir.Path.FullPath))
        .SelectMany(childDirectory=>RecursiveGetFile(context, childDirectory.Path, filter, predicate))
        )
    {
        yield return file;
    }
}

这个脚本的输出将类似于

RepoRoot/test.sln
RepoRoot/src/test.sln
RepoRoot/src/proj1/test.sln
RepoRoot/src/proj2/test.sln
RepoRoot/src/proj3/test.sln
RepoRoot/src/proj4/test.sln

这通过跳过已知的麻烦制造者来消除260个字符的问题,如果其他未知路径也有相同的问题,则无法解决。