Проблема обработки ошибок при использовании Get-Filehash в Powershell, когда файл открыт

Я создал команду для поиска дубликатов файлов в папках (с информацией о длине файла) в Powershell, которая работает нормально, но у меня возникает проблема, когда файл, который я анализирую, открыт.

Это команда:

      Get-ChildItem -Recurse |
select-object length, fullname, @{n="Hash";e={get-filehash -algorithm MD5 -path $_.FullName -ErrorAction SilentlyContinue | Select-object -expandproperty Hash}} | 
Group -Property Hash |
where {$_.Count -gt 1} |
foreach { $_.Group | select fullname, hash, length} |
Export-Csv -Path c:\temp\filelist.csv -Delimiter "`t" -NoTypeInformation

Когда файл открыт, я получаю эту ошибку:

      Group : Object reference not set to an instance of an object.
At line:2 char:164
+ ... tinue | Select-object -expandproperty Hash}} | Group -Property Hash |
+                                                    ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Group-Object], NullReferenceException
    + FullyQualifiedErrorId : System.NullReferenceException,Microsoft.PowerShell.Commands.GroupObjectCommand

Проблема в том, что Get-FileHash завершается с ошибкой и выполнение останавливается при открытии файла.

Я хочу только, чтобы открытые файлы игнорировались и команда продолжалась. Я перепробовал много решений (-ErrorAction SilentlyContinue) безуспешно. Не могли бы вы мне помочь пожалуйста? Спасибо.

1 ответ

Измените свой код, используя цикл вместоSelect-Objectи обработка ошибок для пропуска файлов, в которыхGet-FileHashне удается получить хэш:

      # Add `-File` to ensure the cmdlet outputs files only
Get-ChildItem -Recurse -File -ErrorAction SilentlyContinue |
    ForEach-Object {
        try {
            [pscustomobject]@{
                Length   = $_.Length
                Fullname = $_.FullName
                Hash     = ($_ | Get-FileHash -Algorithm MD5 -ErrorAction Stop).Hash
            }
        }
        catch {
            Write-Warning $_
        }
    } |
    Group-Object -Property Hash |
    Where-Object Count -GT 1 |
    ForEach-Object Group |
    Export-Csv -Path c:\temp\filelist.csv -Delimiter "`t" -NoTypeInformation

Другой альтернативой, которая должна работать, будет использование-PipelineVariableобщий параметр :

      Get-ChildItem -Recurse -File -ErrorAction SilentlyContinue -PipelineVariable pv |
    # Change `-ErrorAction` to `Continue` if you want errors to be displayed
    Get-FileHash -Algorithm MD5 -ErrorAction SilentlyContinue |
    Select-Object *, @{ N='Length'; E={ $pv.Length }} -ExcludeProperty Algorithm |
    Group-Object Hash |
    Where-Object Count -GT 1 |
    ForEach-Object Group |
    Export-Csv ....
Другие вопросы по тегам