在 Powershell 中处理长路径异常

在 Powershell 中处理长路径异常

我是新手,我的 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 上测试和验证):

然后,您只需按如下所示更改脚本中的根路径变量,它就会按预期工作:

  #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 ;

这将为您提供文件列表(全名)。

相关内容