PowerShell扫描超长路径文件报错,无法获取完整列表求解决
处理超长路径文件扫描问题
我需要构建日志记录服务器中路径长度超过255字符的文件,当前PowerShell脚本能识别最长351字符的文件,已找到780个超限制文件,但执行结束时出现大量报错,提示未获取完整列表。
现有脚本
# The path to scan and the the lengths for (sub-directories will be scanned as well). $pathToScan = "\\Server\\" #or "\\Server\\Share\\" # This must be a file in a directory that exists and does not require admin rights to write to. $outputFilePath = "C:\temp\FilePathLengths.txt" $Drive = New-PSDrive "X" -PSProvider FileSystem -Root $pathToScan $DriveLength = $pathToScan.Length $writeToConsoleAsWell = $false # Writing to the console will be much slower. # Open a new file stream and write all the paths and their lengths to it. $outputFileDirectory = Split-Path $outputFilePath -Parent if (!(Test-Path $outputFileDirectory)) { New-Item $outputFileDirectory -ItemType Directory } $stream = New-Object System.IO.StreamWriter($outputFilePath, $false) # Starting effort before this caused errors, tried alternatives # Get-ChildItem -Path $pathToScan -Recurse -Force | Select-Object -Property FullName, @{Name="FullNameLength";Expression={($_.FullName.Length)}} | Sort-Object -Property FullNameLength -Descending | ForEach-Object { Get-ChildItem -Path "X:\" -Recurse -Force | Select-Object -Property FullName, @{Name="FullNameLength";Expression={($_.FullName.Length)}} | Sort-Object -Property FullNameLength -Descending | ForEach-Object { If ($_.FullNameLength -gt 255) { $filePath = $_.FullName $length = $_.FullNameLength $string = "$length | $filePath" # Write to the Console. if ($writeToConsoleAsWell) { Write-Host $string } #Write to the file. $stream.WriteLine($string) } } $stream.Close() Remove-PSDrive "X"
报错信息
Get-ChildItem : 指定的路径、文件名或两者过长。完全限定的文件名必须少于260个字符,目录名必须少于248个字符。 At 'ScriptPath&Name'.ps1:17 char:1 - Get-ChildItem -Path "X:" -Recurse -Force | Select-Object -Property F ... - + CategoryInfo : ReadError: ('FilePath that isn't descriptive enough to actually identify the file' :String) [Get-ChildItem], PathTooLongException + FullyQualifiedErrorId : DirIOError,Microsoft.PowerShell.Commands.GetChildItemCommand
需求目标
我的目标是识别所有VEEAM/VMware在从Server 2012迁移到2022时可能无法正确处理或恢复的目录项,以便批量或单独处理。我已尝试在注册表中启用长路径、使用临时PSDrive缩短路径,但仍有超过350字符的路径触发报错,希望能获取完整的超长路径文件分析结果。
解决方案
1. 改用.NET原生长路径API扫描
PowerShell的Get-ChildItem依赖传统Win32 API,即使启用长路径支持,递归扫描时仍可能触发路径过长错误。改用.NET的System.IO.Directory类方法,原生支持长路径解析:
# 配置参数 $pathToScan = "\\Server\" $outputFilePath = "C:\temp\FilePathLengths.txt" $lengthThreshold = 255 # 创建输出目录(如果不存在) $outputDir = Split-Path $outputFilePath -Parent if (-not (Test-Path $outputDir)) { New-Item $outputDir -ItemType Directory | Out-Null } # 使用.NET API递归获取所有文件和目录 $allItems = @() # 扫描所有文件 $allItems += [System.IO.Directory]::EnumerateFiles($pathToScan, "*", [System.IO.SearchOption]::AllDirectories) # 扫描所有目录 $allItems += [System.IO.Directory]::EnumerateDirectories($pathToScan, "*", [System.IO.SearchOption]::AllDirectories) # 筛选超长路径并写入文件 $stream = New-Object System.IO.StreamWriter($outputFilePath, $false) foreach ($item in $allItems) { $pathLength = $item.Length if ($pathLength -gt $lengthThreshold) { $stream.WriteLine("$pathLength | $item") } } $stream.Close()
2. 确保系统长路径支持生效
- 注册表设置:在
HKLM\SYSTEM\CurrentControlSet\Control\FileSystem下,将LongPathsEnabled(DWORD)设置为1,重启系统后生效 - 环境要求:PowerShell需基于.NET Framework 4.6.2+或.NET Core(Server 2022默认满足)
- SMB共享:确保源服务器(Server 2012)和目标服务器(Server 2022)均启用长路径支持
3. 处理极端超长路径(超过32767字符)
若存在超过32767字符的路径,可添加\\?\前缀强制启用最大长度路径解析:
$longPathPrefix = "\\?\" # 转换为绝对路径并添加前缀 $fullScanningPath = $longPathPrefix + ([System.IO.Path]::GetFullPath($pathToScan)) # 使用带前缀的路径扫描 $allItems = [System.IO.Directory]::EnumerateFiles($fullScanningPath, "*", [System.IO.SearchOption]::AllDirectories) $allItems += [System.IO.Directory]::EnumerateDirectories($fullScanningPath, "*", [System.IO.SearchOption]::AllDirectories)
4. 脚本性能优化
- 禁用控制台输出:保持
$writeToConsoleAsWell = $false,避免IO开销拖慢扫描速度 - 使用
StreamWriter:相比Out-File或Add-Content,直接写入文件流能大幅提升写入效率
内容的提问来源于stack exchange,提问作者Jeremy
相关产品推荐
相关产品推荐

