5

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

Func<IFileSystemInfo, bool> exclude_node_modules = fileSystemInfo=>!fileSystemInfo.Path.FullPath.Contains("node_modules");

var solutions = GetFiles("./**/*.sln", exclude_node_modules);

解决此问题的任何帮助都会有所帮助。

4

1 回答 1

3

为了加快文件系统的递归遍历,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 字符问题,如果其他未知路径有相同的问题,则不会解决。

于 2016-08-05T12:37:27.710 回答