Powershell:指定的路径或文件名或两者都太长 - 目录排除

Powershell: The specified path, or filename, or both, are too long - Directory Excludes

我们之前 运行 这个脚本很好,但最近我们在 TFS Build 的配置转换步骤中遇到了一些问题(见下面的错误)。

$serviceFiles = Get-ChildItem $localWorkspace -Recurse | where {$_.Extension -eq ".exe"}

我们最近改用Gulp来编译我们的CSS和JS,它给了我们一个“node_modules”文件夹。看起来它正在尝试抓取这些文件夹并且实际上达到了目录长度限制。我已经尝试了从谷歌搜索和其他相关问题中找到的各种建议,但 none 似乎对我有用,它仍然遇到同样的错误(我假设实际上并没有排除这些文件夹)

这是我尝试用来排除文件夹的修改版本的示例

$excludedDirectories = @("*node_modules*", "*packages*", "*Common*");
Write-Verbose $localWorkspace

# get services for config types (service configs named same as assmebly .exe)
$serviceFiles = Get-ChildItem $localWorkspace -Recurse -Exclude $excludedDirectories | ?{$_.Extension -eq ".exe" -and $_.FullName -notmatch '*node_modules*' }

我已经根据其他 SO 问题和答案尝试了一些变体,但解决方案让我望而却步。我从一些来源了解到 -Exclude 在大多数情况下对很多人不起作用,所以我尝试了 where 子句的解决方案来排除文件夹(我想排除多个,但我只是尝试 node_modules 看看我是否可以通过它,其他文件夹不太深)

我想排除 node_modules 目录,以及其他几个不需要检查转换的目录。任何帮助将不胜感激,谢谢。

不幸的是,-Exclude 参数不会在枚举所有文件之前排除目录。所以它仍然会出错。您需要更早地排除它们。

如果那些目录只存在于顶层,你可以枚举顶层目录,排除你不想要的目录,然后检查剩余目录中的内容。像这样:

$excludedDirectories = @("node_modules", "packages", "Common")

$serviceFiles = Get-ChildItem $localWorkspace -Exclude $excludedDirectories | % { Get-ChildItem $_ -Recurse } | ? {$_.Extension -eq ".exe" }

此外,您可以使用 -Include:

使这更简单一些
$serviceFiles = Get-ChildItem $localWorkspace -Exclude $excludedDirectories | % { Get-ChildItem $_ -Recurse -Include "*.exe" }

注意我做了什么。我删除了顶级 -Recurse 并过滤掉了那些目录。然后我对最顶层父级的剩余子级使用了 -Recurse,为我们提供了我们正在寻找的文件。

如果你需要过滤掉的目录出现在层级的深处或者多层,你就得自己写递归遍历函数了:

function Get-ChildItemRecursiveExclude(
    [Parameter(Mandatory=$true)][string[]]$Path,
    [Parameter(Mandatory=$true)][string[]]$ExcludedDirNames
) {
    $immediateChildren = Get-ChildItem $Path -Exclude $ExcludedDirNames
    foreach ($c in $immediateChildren) {
        # Uncaptured output is returned
        $c
        if (Test-Path $c -PathType Container) {
            Get-ChildItemRecursiveExclude $c $ExcludedDirNames
        }
    }
}

$serviceFiles = Get-ChildItemRecursiveExclude $localWorkspace @("node_modules", "packages", "Common") | ? { $_.Extension -eq ".exe" }

总体而言,基本思想是您必须首先阻止 PowerShell 向下遍历 node_modules。 npm 创建了非常深的层次结构,超过了旧的路径长度限制。 (我不是很清楚为什么 .NET 仍然强制执行它们,但即使某些底层 Windows API 不再执行,它仍然执行。例如,robocopy 和几个第三方运行时,如 Node,别理他们。)