在设置现有文件属性时出现“找不到路径的一部分”错误。

3
我编写了一个PowerShell脚本,以删除指定根路径下所有文件的R/H/S属性。相关代码如下:
$Mask = [System.IO.FileAttributes]::ReadOnly.Value__ -bor [System.IO.FileAttributes]::Hidden.Value__ -bor [System.IO.FileAttributes]::System.Value__
Get-ChildItem -Path $Paths -Force -Recurse -ErrorAction SilentlyContinue | ForEach-Object {
    $Value = $_.Attributes.value__
    if($Value -band $Mask) {
        $Value = $Value -band -bnot $Mask
        if($PSCmdlet.ShouldProcess($_.FullName, "Set $([System.IO.FileAttributes] $Value)")) {
            $_.Attributes = $Value
        }
    }
}

这个代码很好用,但是当我处理一个非常大的文件夹结构时,出现了一些类似于这样的错误:

Exception setting "Attributes": "Could not find a part of the path 'XXXXXXXXXX'."
At YYYYYYYYYY\Grant-FullAccess.ps1:77 char:17
+                 $_.Attributes = $Value
+                 ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], SetValueInvocationException
    + FullyQualifiedErrorId : ExceptionWhenSetting

我认为这很奇怪,因为被处理的FileInfo对象是有保证存在的,因为它来自于文件搜索。

我不能给出文件名,因为它们是机密的,但我可以说:

  • 它们的长度为113-116个字符
  • 涉及的唯一字符集是%()+-.0123456789ABCDEFGIKLNOPRSTUVWX,其中没有一个是非法的文件名字符
  • 由于URL编码空格,所以有%字符 (%20)

您有什么建议可能会导致这种情况发生吗?我认为如果完整路径太长,或者我没有写入文件的权限,那么应该抛出一个更合适的错误。


这些是 UNC 路径(\server\share\restofpath)还是本地路径? - Theo
1
@mklement0:我的意图是处理目录和文件,但还是谢谢你的提示。 - Christian Hayter
1
@mklement0:关于长路径前缀,我现在怀疑这是一个长路径问题。我今天会尝试一下。 - Christian Hayter
@Theo:路径将始终在本地驱动器上。 - Christian Hayter
2个回答

3

如您在您自己的回答中所述,问题的原因是路径过长(超出了遗留限制的259个字符)。

除了通过组策略启用长路径支持外,您还可以按以下方式在每台计算机上通过注册表启用它,需要以提升权限运行(作为管理员)

# NOTE: Must be run elevated (as admin).
# Change will take effect in FUTURE sessions.
Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem LongPathsEnabled 1

将0传递给函数以关闭支持。


然而,即使在不支持长路径的情况下(这在Windows10之前的版本中总是如此),也可以处理长路径:

  • Windows PowerShell(PowerShell版本低于5.1),您必须使用长路径加入前缀\\?\,如下所述。

  • 在PowerShell [Core] v6+中,不需要额外工作,因为它始终支持长路径 - 您既不需要在整个系统范围内打开支持,也不需要下面讨论的长路径前缀。

    • 注意:虽然原则上您也可以在PowerShell [Core] 中使用\\?\,但截至v7.0.0-rc.2,对其的支持不一致;请参阅GitHub问题# 10805

重要提示:前缀\\?\仅在以下条件下起作用:

  • 前缀路径必须是完整(绝对)规范化路径(不能包含..组件)。

    • 例如,\\?\C:\path\to\foo.txt起作用,但\\?\.\foo.txt则不起作用。
    • 此外,如果路径是UNC路径,则路径需要不同的形式
      • \\?\UNC\<server>\<share>\...
      • 例如,\\server1\share2必须表示为\\?\UNC\server1\share2

0

最终,尽管错误消息的措辞不同,但它确实成为了一个长路径问题。使用简单的 Get-ChildItem 搜索文件会产生相同的错误。我最终跟踪到了在错误消息中提到的文件,并测量了它们的总路径长度。它们超过了260个字符。

我尝试添加\\?\前缀到路径中进行实验,但PowerShell似乎不喜欢这种语法。

幸运的是,该脚本正在Windows 2016上使用,因此我尝试在组策略中启用长路径支持,问题就解决了。


\\?\ 可以与 Get-Item / Get-ChildItem 一起使用,但仅适用于完整的、规范化的路径。在 PowerShell Core 中,如果您使用 -LiteralPath,它们还只能工作 - 请参阅我的答案。有趣的是,您最初在 $_.Attributes = $Value 中没有明确的路径参数而得到了一个错误;这几乎表明 .Attributes 属性实现中存在一个 bug,但我无法重现它。 - mklement0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接