我是新手,我的 powershell 脚本遇到长路径问题。此脚本旨在从文件/文件夹及其子文件夹中获取相对路径和哈希值。它与其他一些文件一起工作,我收到以下错误:
Get-ChildItem:指定的路径、文件名或两者太长。完全限定文件名必须少于 260 个字符,目录名必须少于 248 个字符。
我想知道如何处理这个问题并避免出现这个错误。
我已经在运行脚本的 Windows Server 2012 中启用了长文件路径,但它仍然不起作用。
如果我添加这个\\?\在路径变量中,即使我添加-LiteralPath,它也会失败,说路径中有非法字符。
任何帮助都很好
这是我的powershell脚本:
#Message to user
Write-Output "`nThis script will collect the FilePathName, Name, RelativePath and the Hash of the files/folders you have chosen."
"`nAt the end, it will tell you how long it took to run the script"
Read-Host -Prompt "`nPress ENTER to continue or CTRL+C to quit"
#Counting the time from the beginning
$starttime = (Get-Date)
#Variables
#Can only be added 3 paths maximum. If added more than 3 it may change the relatrive path
$root = "C:\mypath"
#Variable for creating the CSV File
$report = "mycsvfile.csv"
#Process for generating the HASH
$hasher = [System.Security.Cryptography.SHA256]::Create()
$AllFiles = @()
"`n"#line space
Write-Host "Generating the Hash from $root"
#Getting information from directories
foreach ($file in get-childitem $root -recurse | Select-Object FullName, Directory, Name, PSIsContainer, Length)
{
$acl = get-acl $file.fullname | select-object owner,accesstostring,group
$obj = new-object psObject
#Generating HASH File
if(!$file.PsIsContainer)
{
$relativePath = $file.FullName.Substring($root.Length)
Write-Host "Debug $relativePath" -ForegroundColor Green
$inputStream = New-Object IO.StreamReader $file.fullname
$hashBytes = $hasher.ComputeHash($inputStream.BaseStream)
$inputStream.Close()
$builder = New-Object System.Text.StringBuilder
$hashBytes | Foreach-Object { [void] $builder.Append($_.ToString("X2")) }
#Add info into CSV FILE
$obj | Add-Member -membertype noteproperty -name FilePathandName -Value $file.FullName
$obj | Add-Member -membertype noteproperty -name Name -Value $file.Name
$obj | Add-Member -MemberType noteproperty -Name RelativePath -Value $relativePath #-force
$obj | Add-Member -MemberType noteproperty -Name Hash -Value $builder.ToString()
#$obj | Add-Member -membertype noteproperty -name CreationTime -Value $file.CreationTime
#$obj | Add-Member -MemberType noteproperty -Name LastAccessTime -Value $file.LastAccessTime
#$obj | Add-Member -MemberType noteproperty -Name LastWriteTime -Value $file.LastWriteTime
#Variable to send info to CSV
$AllFiles += $obj
Clear-Variable relativePath
}
Remove-Variable obj
}
#$AllFiles += $obj
#Generating CSV FILE
$AllFiles |Export-Csv $report –NoTypeInformation
"`n"
Write-Host "$report File has been created "
"`n"
Write-Host "The script took:`n"
$endTime = Get-Date
New-TimeSpan -Start $startTime -End $endTime
答案1
为了使 Powershell cmdlet 正常工作,请使用\\?\您需要安装这些组件的以下最低版本(在 Windows Server 2012 R2 上测试和验证):
- Windows 管理框架 5.1
- .NET Framework 4.6.2
然后,您只需按如下所示更改脚本中的根路径变量,它就会按预期工作:
#Variables
#Can only be added 3 paths maximum. If added more than 3 it may change the relative path
$root = "\\?\C:\mypath\"
无需更改任何注册表项即可启用对长路径的支持或对任何 cmdlet 使用 -LiteralPath 参数。我在其他文章和论坛中多次看到这些说法,但除了非常老版本的 Windows 外,这并不正确。
现在,如果您无法安装这些较新的版本,您将不得不使用变通方法。
请注意,在您的脚本中,以下功能受到此问题的影响:
- 获取子项
- 获取 Acl
- 新对象 IO.StreamReader
一个解决方案是将部分路径替换为驱动器当它变得太长时,使用新驱动器作为根文件夹。我尝试使用替代命令,但它应该使用新-PSDrivecmdlet。这需要在脚本中添加一些逻辑,但并不需要太多努力,而且相当容易。
现在,如果你想在进行任何替换之前获取所有文件的列表(因此您可以首先检查所有路径和文件名的长度),您可以使用以下解决方法:
$root = "C:\mypath\" ;
$AllFiles = cmd /c dir $root /b /s /a-d ;
这将为您提供文件列表(全名)。