【问题标题】:Calling a Function During Array Creation to export contents of folder containing Zip files在数组创建期间调用函数以导出包含 Zip 文件的文件夹的内容
【发布时间】:2022-02-13 04:21:29
【问题描述】:

我在尝试调用脚本的函数时遇到问题,该脚本用于在我的 PC 上的文件夹中构建 zip 文件列表。我需要创建的最后一个 CSV 是一个包含未压缩大小的 zip 文件列表。这是我到目前为止的内容(从几篇文章编译而来):

获取未压缩大小的函数:

function Get-UncompressedZipFileSize {

param (
    $Path
)

$shell = New-Object -ComObject shell.application
$zip = $shell.NameSpace($Path)
$size = 0
foreach ($item in $zip.items()) {
    if ($item.IsFolder) {
        $size += Get-UncompressedZipFileSize -Path $item.Path
    } else {
        $size += $item.size
    }
}


[System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$shell) | Out-Null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

return $size
}

这是我的数组创建:

$arr = @()
gci C:\zips -recurse | ? {$_.PSIsContainer -eq $False} | % {
$obj = New-Object PSObject
$obj | Add-Member NoteProperty Name $_.Name
$obj | Add-Member NoteProperty FullPath $_.FullName
$arr += $obj
}
$arr | Export-CSV -notypeinformation c:\zips

我坚持在我的数组中创建一个新成员对象,该对象将调用 get-uncompressedzipfilesize 函数将该大小作为我的 zip 中的新列传递回数组。这样的事情有可能吗?

【问题讨论】:

  • 您使用的是哪个 PowerShell 版本?
  • 嘿,我用的是5.1版

标签: powershell


【解决方案1】:

为了简单起见,由于您只是调用函数来获取当前文件夹的大小 (zip),因此您可以为此使用 Calculated Property

$Path = "C:\Zips"
Get-ChildItem -Path $Path -Directory -Recurse | 
    Select-Object -Property Name, FullName,
    @{
        Name = "Size"
        Expression = {
            Get-UncompressedZipFileSize -Path $_.FullName
        }
    } | Export-Csv -Path "$Path\zip.csv" -Force -NoTypeInformation -Append 

另一方面,如果您发现自己显式添加到数组中,请利用 PowerShell 的管道流。

$Path = "C:\Zips"
Get-ChildItem -Path $Path -Directory -Recurse | 
    ForEach-Object -Process {
        [PSCustomObject]@{
            Name = $_.Name
            FullPath = $_.FullName
            Size = Get-UncompressedZipFileSize -Path $_.FullName
        } | Export-Csv -Path "$Path\zip.csv" -Force -NoTypeInformation -Append 
    }

添加到固定数组 (+=)计算成本高如果你有一个大目录),它是减缓。固定数组就是说,它们是固定大小的,为了让你添加到它,它需要被分解和重新创建。 arraylist 的替代解决方案,但在这种情况下 - 并且在大多数情况下 - 它是不需要的。

  • Get-ChildItem 还包括一个 -Directory 开关,用于仅搜索文件夹。在 V3 中呈现。
  • 我建议您同时搜索压缩文件夹的文件扩展名,这样您在使用-Filter 时就不会遇到任何问题。

【讨论】:

  • 很好,虽然我不知道那些糟糕的数组会被分解 :)
  • 我想我在“PowerShell in Practice”一书中读到了这一点。大声笑可能是错的
  • :) 好吧,我想最终 garbage-collecting 旧数组可以被认为是分解它......
  • 垃圾收集内置在 .NET 中并按需执行,因此很少需要在用户代码中显式控制它,尽管可以通过 [GC] 类进行控制;链接的主题还指向背景信息。
  • 谢谢谢谢谢谢!!我最终选择了计算属性解决方案并创建了自己的数组并调用了我的自定义函数!!万岁!
【解决方案2】:

这是使用ZipFile Class 的替代方法。 SizeConvert 函数的灵感来自 this answerGet-ZipFileSize 的输出将是 Zip 文件的绝对路径压缩和扩展大小以及格式化大小(即: 7.88 MB 而不是 8262942)。

using namespace System.IO
using namespace System.IO.Compression
using namespace System.Linq

function SizeConvert {
[cmdletbinding()]
param(
    [object]$Length,
    [int]$DecimalPoints = 2
)

    $suffix = "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"
    $index = 0
    while ($Length -ge 1kb) {
        $Length /= 1kb
        $index++
    }
    return [string]::Format(
        '{0} {1}',
        [math]::Round($Length, $DecimalPoints), $suffix[$index]
    )
}

function Get-ZipFileSize {
[cmdletbinding()]
param(
    [parameter(ValueFromPipeline)]
    [FileInfo]$Path
)
    process {
        try
        {
            $zip = [ZipFile]::OpenRead($Path.FullName)
            $compressedSize = [Enumerable]::Sum([int64[]]$zip.Entries.CompressedLength)
            $expandedSize = [Enumerable]::Sum([Int64[]]$zip.Entries.Length)

            [pscustomobject]@{
                FilePath            = $Path.FullName
                RawExpanded         = $expandedSize
                RawCompressed       = $compressedSize
                FormattedExpanded   = SizeConvert $expandedSize -DecimalPoints 3
                FormattedCompressed = SizeConvert $compressedSize -DecimalPoints 3
            }
        }
        catch
        {
            $PSCmdlet.WriteError($_)
        }
        finally
        {
            if($zip -is [System.IDisposable]) {
                $zip.Dispose()
            }
        }
    }
}

Get-ChildItem -Filter *.zip -Recurse | Get-ZipFileSize | Export-Csv ....

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多