【问题标题】:Calculate the hash of a file longer than 256 characters?计算长度超过 256 个字符的文件的哈希值?
【发布时间】:2020-12-18 22:11:39
【问题描述】:

我正在使用Boe Prox's script 打印目录中所有文件和文件夹的列表。我需要 Prox 的脚本(与其他 Windows 打印目录命令相反),因为它使用 robocopy 打印长度超过 260 个字符的文件路径。

我的问题是,我还希望将文件哈希与文件名一起打印。我已经修改了脚本以获取哈希值(请参见下文),它通常可以工作,除非文件路径长于 260 个字符。长文件路径在最终输出的哈希列中为空白。

我做过的研究:

尝试解决问题:

  • 我还尝试修改 filehash 的语法,使其更符合脚本的其余部分,即。 Hash = $matches.Hash (这将返回所有空白来代替文件哈希)
  • 我尝试删除似乎指定项目而不是项目内容的正则表达式部分,即:If ($_.Trim() -match "^(?<Children>\d+)\s+") { (这会导致错误代码WARNING: Cannot bind argument to parameter 'Path' because it is null.

我非常希望这可以发生:Boe 的原始脚本中的 cmets 包括以下行:“1.1 版 - 增加了计算文件哈希的能力”

这是我的(部分工作脚本):

Function Get-FolderItem {

    [cmdletbinding(DefaultParameterSetName='Filter')]
    Param (
        [parameter(Position=0,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
        [Alias('FullName')]
        [string[]]$Path = $PWD,
        [parameter(ParameterSetName='Filter')]
        [string[]]$Filter = '*.*',    
        [parameter(ParameterSetName='Exclude')]
        [string[]]$ExcludeFile,              
        [parameter()]
        [int]$MaxAge,
        [parameter()]
        [int]$MinAge
    )
    Begin {
        $params = New-Object System.Collections.Arraylist
        $params.AddRange(@("/L","/E","/NJH","/BYTES","/FP","/NC","/XJ","/R:0","/W:0","T:W"))
        If ($PSBoundParameters['MaxAge']) {
            $params.Add("/MaxAge:$MaxAge") | Out-Null
        }
        If ($PSBoundParameters['MinAge']) {
            $params.Add("/MinAge:$MinAge") | Out-Null
        }
    }
    Process {
        ForEach ($item in $Path) {
            Try {
                $item = (Resolve-Path -LiteralPath $item -ErrorAction Stop).ProviderPath
                If (-Not (Test-Path -LiteralPath $item -Type Container -ErrorAction Stop)) {
                    Write-Warning ("{0} is not a directory and will be skipped" -f $item)
                    Return
                }
                If ($PSBoundParameters['ExcludeFile']) {
                    $Script = "robocopy `"$item`" NULL $Filter $params /XF $($ExcludeFile  -join ',')"
                } Else {
                    $Script = "robocopy `"$item`" NULL $Filter $params"
                }
                Write-Verbose ("Scanning {0}" -f $item)
                Invoke-Expression $Script | ForEach {
                    Try {
                        If ($_.Trim() -match "^(?<Children>\d+)\s+(?<FullName>.*)") {
                           $object = New-Object PSObject -Property @{
                                FullName = $matches.FullName
                                Extension = $matches.fullname -replace '.*\.(.*)','$1'
                                FullPathLength = [int] $matches.FullName.Length
                                Length = [int64]$matches.Size
                                FileHash = (Get-FileHash -Path $matches.FullName).Hash
                                Created = (Get-Item $matches.FullName).creationtime
                                LastWriteTime = (Get-Item $matches.FullName).LastWriteTime
                            } 
                            $object.pstypenames.insert(0,'System.IO.RobocopyDirectoryInfo')
                            Write-Output $object
                        } Else {
                            Write-Verbose ("Not matched: {0}" -f $_)
                        }
                    } Catch {
                        Write-Warning ("{0}" -f $_.Exception.Message)
                        Return
                    }
                }
            } Catch {
                Write-Warning ("{0}" -f $_.Exception.Message)
                Return
            }
        }
    }
}


Get-FolderItem "C:\TestingFileFolders" 

【问题讨论】:

  • 你的系统上有enabled long paths吗?
  • 试试Get-FileHash -Path "\\?\$($matches.FullName)"
  • 脚本适用于我(Win10,启用长路径),文件路径为 795 个字符。还有一个错误,它也尝试计算目录的哈希值。
  • @zett42 我不知道有这样的能力,我将在下次与 IT 部门的会议上提出它。谢谢!
  • 顺便说一句,启用长路径后,Get-FileHash 在 PS5 和 PS7.1 中使用 >260 个字符的路径。奇怪的是,在 PS5 中,您的脚本不会像在 PS7.1 中那样报告目录错误。

标签: powershell directory robocopy filehash


【解决方案1】:

Windows PowerShell 中,您可以prepend \\?\ 到完整路径并读取文件:

Get-FileHash -Path "\\?\$($matches.FullName)"

【讨论】:

  • 确实如此。请注意,在 PowerShell [Core] v6+ 中,此前缀不仅从不需要,而且实际上会导致问题:请参阅GitHub issue #10805
  • 我不确定这是否应该是一个新问题,但如何让输出仅包含 64 位哈希?适合我的正则表达式是('Hash=(\w{64})'),但我不知道如何将它添加到Get-FileHash -Path "\\?\$($matches.FullName)"
  • Get-FileHash -Path "\\?\$($matches.FullName)" |Select -Expand Hash
  • 我真的很感激 - 我可能需要很长时间才能弄清楚。
猜你喜欢
  • 1970-01-01
  • 2010-12-17
  • 2011-11-02
  • 2020-11-18
  • 1970-01-01
  • 1970-01-01
  • 2019-07-21
  • 2016-01-18
  • 2014-06-02
相关资源
最近更新 更多