在PowerShell ForEach-Object循环中,是否可以每1000个条目将内容转储到日志文件中?

fslejnso  于 5个月前  发布在  Shell
关注(0)|答案(1)|浏览(67)

如果我使用PowerShell ForEach-Object语句,并将内容存储在变量中,是否可以每1000个条目将这些内容转储到日志文件中?
我之所以这么问,是因为我处理的文件有几万行,如果不是几十万行的话,可能需要几个小时来处理。如果计算机或程序崩溃,我至少希望将其中的一部分保存到日志文件中。一次输出一行似乎也会减慢处理速度。
(EDIT:向代码添加了额外的内容,我想我试图简化它并没有给自己带来任何好处)
范例:

$count = 1
Get-ChildItem -Path "$path" -Recurse -File | ForEach-Object {
    $fileinfo = $_
    $FullName = $fileinfo.FullName -replace [regex]::Escape("$hashpath"), ''
    $LastWriteTime = $fileinfo.LastWriteTime.ToString('yyyyMMdd_HHmss)
    Write-Host "$count of $numfiles $FullName $($fileinfo.Length) $LastWriteTime"
    $count++
    $filehash = (Get-FileHash -LiteralPath $fileinfo.FullName -Algorithm SHA256).Hash
    "$FileHash $FullName $($fileInfo.Length) $LastWriteTime"
} | Out-File -Encoding UTF8 -FilePath $hashlog

字符串
我正在考虑使用一个计数器,但不知道我将如何只捕获每1000部分。感谢任何帮助。
编辑:我试图实现的输出:

[SHA256HASHOUTPUT] [RELATIVE FILE PATH] [FILE SIZE] [DATETIMESTAMP]
0123456789012345678901234567890123456789012345678901234567891234 \file1.txt 345 20231129_130623

kdfy810k

kdfy810k1#

您可以使用List<T>在输出到文件之前缓冲散列,并使用匿名函数处理当.Count到达该缓冲区时输出到文件的逻辑。
值得注意的是:

  • Format-Table -AutoSize在你的代码中根本不需要,并且通过延迟输出到文件来影响它的性能。最有可能的是,像这样的东西将给予非常相似的性能,并且不需要缓冲:
Get-ChildItem -Path $path -Recurse -File |
    Get-FileHash -Algorithm SHA256 |
    ForEach-Object Hash |
    Out-File $hashlog -Encoding utf8

字符串

  • .Trim()不需要.Hash值。
  • Get-ChildItem的输出可以直接通过管道传输到Get-FileHash
Get-ChildItem -Path $path -Recurse -File |
    Get-FileHash -Algorithm SHA256 | & {
        begin {
            # tweak the amount of lines to hold before outputing to file
            $buffersize = 1000
            $list = [System.Collections.Generic.List[string]]::new($buffersize)
        }
        process {
            # add the Hash to the List
            $list.Add($_.Hash)
            # if the List size is equal to the buffer size
            if ($list.Count -eq $buffersize) {
                # output the content to the file
                $list.ToArray()
                # and clear the list
                $list.Clear()
            }
        }
        end {
            # if there is any remaining data
            if ($list.Count) {
                # output it to the file
                $list.ToArray()
            }
        }
    } |
    Out-File $hashlog -Encoding utf8


对于更新后的问题,如果你想重用缓冲逻辑,你可以这样做:

Get-ChildItem -Path $path -Recurse -File -PipelineVariable file |
    Get-FileHash -Algorithm SHA256 | & {
        begin {
            # tweak the amount of lines to hold before outputing to file
            $buffersize = 1000
            $list = [System.Collections.Generic.List[string]]::new($buffersize)
        }
        process {
            $line = '{0} {1} {2} {3}' -f
                $_.Hash,
                $file.FullName.Remove(0, $path.Length),
                $file.Length,
                $file.LastWriteTime.ToString('yyyyMMdd_HHmss')

            $list.Add($line)

            # if the List size is equal to the buffer size
            if ($list.Count -eq $buffersize) {
                # output the content to the file
                $list.ToArray()
                # and clear the list
                $list.Clear()
            }
        }
        end {
            # if there is any remaining data
            if ($list.Count) {
                # output it to the file
                $list.ToArray()
            }
        }
    } | Out-File -Encoding UTF8 -FilePath $hashlog

相关问题