Powershell 使用新PSDrive处理路径过长异常

Powershell 使用新PSDrive处理路径过长异常,powershell,Powershell,我正在递归深层文件夹结构,以便检索所有文件夹路径,如下所示: $subFolders = Get-ChildItem $rootFolder -Recurse -Directory -ErrorVariable folderErrors | Select-Object -ExpandProperty FullName 注意:$rootFolder在我的例子中是一个网络共享。i、 e.“\\server\DeptDir$\somefolder” $folderErrors变量正确捕获了所有Fi

我正在递归深层文件夹结构,以便检索所有文件夹路径,如下所示:

$subFolders = Get-ChildItem $rootFolder -Recurse -Directory  -ErrorVariable folderErrors | Select-Object -ExpandProperty FullName
注意:$rootFolder在我的例子中是一个网络共享。i、 e.“\\server\DeptDir$\somefolder”

$folderErrors
变量正确捕获了所有FileToolLong异常,因此我想使用长路径创建新的PSDrive,以便递归这些长路径

因此,我使用此cmdlet创建了一个新的PSDrive:

new-psdrive -Name "long1" -PSProvider FileSystem -Root $folderErrors[0].CategoryInfo.TargetName
然而,在创建了一个新的PSDrive之后,我仍然会遇到PathTooLong异常

PS C:\>> cd long1:
PS long1:\>> dir
dir : The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
At line:1 char:1
+ dir
+ ~~~
    + CategoryInfo          : ReadError: (\\svr01\Dep...\Fibrebond ECO\:String) [Get-ChildItem], PathTooLongException
    + FullyQualifiedErrorId : DirIOError,Microsoft.PowerShell.Commands.GetChildItemCommand
我看这个问题没有别的解决办法。我做错什么了吗?当我在路径过长的位置创建驱动器时,为什么新的PSDrive会抛出PathTooLong


谢谢

自Windows周年纪念更新以来,现在有一个本地策略可用

要求如下:

  • Windows管理框架5.1

  • .Net Framework 4.6.2或更高版本

  • Windows 10/Windows server 2016(版本1607或更高版本)

可以使用以下代码段启用此策略

#GPEdit location:  Configuration>Administrative Templates>System>FileSystem 
Set-ItemProperty 'HKLM:\System\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -value 1
否则,通过调用unicode版本的Windows API,实际上可以访问长度超过260个字符的路径

不过有个陷阱。 此功能仅在Powershell 5.1中最低限度起作用

从这里开始,不要以标准方式拨打电话:

get-childitem -Path 'C:\Very long path' -Recurse  
您需要使用以下前缀:
\\?\

范例

get-childitem -LiteralPath '\\?\C:\Very long path' -Recurse 
对于UNC路径,这略有不同,前缀是
\\?\UNC\
,而不是
\\

get-childitem -LiteralPath '\\?\UNC\127.0.0.1\c$\Very long path\' -Recurse
重要

调用
Get ChildItem
unicode版本时,应使用
-LiteralPath
参数,而不是
Path

来自Microsoft文档

-LiteralPath

指定一个或多个位置的路径。与-Path参数不同,-LiteralPath参数的值的使用与键入的值完全相同。没有字符被解释为通配符。如果路径包含转义字符,请用单引号将其括起来。单引号告诉Windows PowerShell不要将任何字符解释为转义序列

示例

(get-childitem -LiteralPath '\\?\UNC\127.0.0.1\This is a folder$' -Recurse) | 
ft @{'n'='Path length';'e'={$_.FullName.length}}, FullName 
输出

下面是我为创建超长存储库所做的实际功能测试,查询它以生成上面的输出,并确认我可以创建包含260个字符的存储库并查看它们

Function CreateVeryLongPath([String]$Root,[Switch]$IsUNC,$FolderName = 'Dummy Folder',$iterations = 200) {
    $Base = '\\?\'
    if ($IsUNC) {$Base = '\\?\UNC\'}

    $CurrentPath = $Base + $Root + $FolderName + '\'

    For ($i=0;$i -le $iterations;$i++) {

    New-Item -Path $CurrentPath -Force -ItemType Directory | Out-Null
    $currentPath = $CurrentPath +  $FolderName + '\'
    }
}

Function QueryVeryLongPath([String]$Root,[Switch]$IsUNC) {
    $Base = '\\?\'
    if ($IsUNC) {$Base = '\\?\UNC\';$Root = $Root.substring(2,$Root.Length -2)}

    $BasePath = $Base + $Root
    Get-ChildItem -LiteralPath $BasePath -Recurse | ft @{'n'='Length';'e'={$_.FullName.Length}},FullName
}



CreateVeryLongPath -Root 'C:\__tmp\' -FolderName 'This is a folder'
QueryVeryLongPath -Root 'C:\__tmp\Dummy Folder11\' 

#UNC - tested on a UNC share path 
CreateVeryLongPath -Root '\\ServerName\ShareName\' -FolderName 'This is a folder' -IsUNC
QueryVeryLongPath -Root '\\ServerName\ShareName\' -IsUNC
值得一提

在我的研究中,我看到有人提到使用RoboCopy,然后解析它的输出。我不是特别喜欢这种方法,所以我不会详细说明。 (编辑:几年后,我发现Robocopy是Windows的一部分,而不是第三方实用程序。我想这也是一个不错的方法,尽管我更喜欢纯Powershell解决方案)

我还看到有人提到过几次,这是一个允许克服260个字符限制的库。它在Github上是开源的,甚至在Technet上有一个(我没有测试过)基于它构建的
Get AlphaFSChildItem

其他参考资料


使用
subst
而不是
New PSDrive
。这看起来很有希望,但没有……不起作用。。一无所获。我应该说这是一个网络共享。因此,在我的例子中使用您的示例将如下所示:Get ChildItem-Path“\\?\server\DeptDirs$\SomeFolder”-Recurse-Directory@ChiliYago实际上,对于UNC,前缀从\\?\到\\?\UNC\YourServer。请参阅我的编辑中的最后一个示例。我正在运行脚本的计算机是PS5,但在托管共享文件夹的计算机上,这是不太可能的。我的下一次尝试返回错误:路径中包含非法字符。获取ChildItem-LiteralPath“\\?\UNC\somesever\myshare$\folder1\folder2\folder3”-Recurse-Directory,供其他人(如我)查找Powershell 5.1;安装Windows管理框架(WMF)5.1,其中包括Powershell 5.1。选择正确的安装文件非常重要。对于服务器2012 R2,我必须选择Win8.1和W2K12R2-KB3191564-x64.msu。然后Unicode Windows API的新前缀对我起作用了!如果我在三周前知道这一点,我会节省很多时间。相反,我映射驱动器、操纵字符串、尝试解析robocopy输出,并且通常浪费大量时间。啊!