【问题标题】:Measure multiple properties?测量多个属性?
【发布时间】:2021-06-16 05:24:26
【问题描述】:

我想使用 Get-ChildItem 查询一个目录,并创建一个包含路径、大小(以 Gb 为单位)、MinimumCreationTime、MaximumCreationTime 等列的表。在 foreach 循环中,我编写了 3 个测量命令。是否可以用一个命令测量多个属性?

$pathes = @'
C:\open
C:\games
'@.Split([System.Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries)

foreach ($path in $pathes){
    Get-ChildItem $path -Recurse | Measure Length -Sum 
    Get-ChildItem $path -Recurse | Measure CreationTime -Minimum
    Get-ChildItem $path -Recurse | Measure CreationTime -Maximum
    }

【问题讨论】:

    标签: powershell measure get-childitem powershell-5.1


    【解决方案1】:

    是否可以用一个命令测量多个属性?

    是的,你可以 - 只是不是你需要的方式

    我们在这里不能完全整合所有三个调用的原因是Measure-Object 将对每个输入属性执行所有请求的计算 - 它不能有意义计算多个[datetime] 值的总和。

    所以充其量,我们只需向Measure-Object 发送 2 轮管道即可:

    $paths = 'C:\open','C:\games'
    
    foreach ($path in $paths){
        # Let's call Get-ChildItem ONCE, and store the result
        $children = Get-ChildItem $path -Recurse 
    
        # Now let's do our calculations
        $fileSize = $children | Measure Length -Sum 
        $newAndOld = $children | Measure CreationTime -Minimum -Maximum
    
        # And finally create a new object to hold the details we calculated above
        [pscustomobject]@{
          Path           = $path
          TotalSize      = $fileSize.Sum
          OldestFileTime = $newAndOld.Minimum
          NewestFileTime = $newAndOld.Maximum
        }
    }
    

    当显示具有 4 个或更少属性的对象时,PowerShell 将默认为表格格式,因此您可以期望 shell 中的默认输出是这样的(取决于语言环境):

    Path      TotalSize OldestFileTime       NewestFileTime
    ----      --------- --------------       --------------
    C:\open  1234567890 1/1/2018 2:00:00 AM  1/31/2021 7:45:00 PM
    C:\games 1234567890 1/1/2018 2:00:00 AM  1/31/2021 7:45:00 PM
    

    【讨论】:

      【解决方案2】:

      使用将CreationTime 属性转换为数字类型的计算属性,可以通过一次调用Measure-Object 命令来实现。现在-Sum 可以使用它(尽管我们将丢弃CreationTime 的总和)。

      计算统计数据后,我们将转换回[DateTime] 以获得有意义的显示值。

      自 PS 7+ 起,计算属性可用作 Measure-Object 参数。对于旧的 PS 版本,我们可以使用Select-Object 来创建计算属性。

      PS 7+ 解决方案

      foreach ($path in $pathes){
      
          $stats = Get-ChildItem $path -File -Recurse | 
                   Measure-Object 'Length', { $_.CreationTime.Ticks } -Sum -Minimum -Maximum
      
          # Create the output for one table row
          [PSCustomObject]@{
              Path                = $path
              'Size(GB)'          = [math]::Round( $stats[0].Sum / 1GB, 2 )   # 2 = number of digits
              MinimumCreationTime = [DateTime] [Int64] $stats[1].Minimum
              MaximumCreationTime = [DateTime] [Int64] $stats[1].Maximum
          }
      }
      

      说明:

      • 我们在对Measure-Object 的调用中指定了两个属性:
        • 第一个属性只是Length
        • 第二个属性是calculated property,这意味着它通过运行一个小脚本块来获取它的值。脚本块将CreationTime 转换为Int64 并将其用作将要测量的值。
      • Measure-Object 指定多个属性时,它会输出一个数组,其中包含每个属性的对象,其中包含统计信息。
        • $stats[0] 包含 SumMinimumMaximum 用于 Length 属性,其中我们只取 Sum
        • $stats[1] 包含SumMinimumMaximum 用于CreationTime 属性,其中我们只取MinimumMaximum。注意Measure-Object 产生[double] 类型的输出,所以我们首先必须转换回[Int64],然后才能最终转换回[DateTime]

      PS 5 解决方案

      foreach ($path in $pathes){
      
          $stats = Get-ChildItem $path -File -Force | 
              Select-Object Length, @{ name = 'CreationTimeTicks'; expression = { $_.CreationTime.Ticks } } | 
              Measure-Object Length, CreationTimeTicks -Sum -Minimum -Maximum
      
          # Create the output for one table row - identical to PS 7+ solution
          [PSCustomObject]@{
              Path                = $path
              'Size(GB)'          = [math]::Round( $stats[0].Sum / 1GB, 2 )   # 2 = number of digits
              MinimumCreationTime = [DateTime] [Int64] $stats[1].Minimum
              MaximumCreationTime = [DateTime] [Int64] $stats[1].Maximum
          }
      }
      

      说明:

      这类似于 PS 7+ 的解决方案,只是我们使用 Select-Object 创建了一个名为 CreationTimeTicks 的计算属性,因此我们可以将其按名称传递给 Measure-Object 调用。

      结论

      虽然这段代码似乎可以工作,但this answer 提供的代码在概念上更清晰,所以我会采用它。

      【讨论】:

      • 错误:在任何对象的输入中都找不到属性“$_.CreationTime.Ticks”。
      • @user2978216 您是否为Get-ChildItem 指定了参数-File
      • 不,我只是复制了您的代码。我需要放东西吗?
      • @zett42 Measure-Object 最近才更新为接受属性表达式 (7.x),在此之前(包括 WPS 的所有版本)它只接受字符串 - 所以它只支持命名属性,未计算的
      • 添加了一个 PS 5 解决方案,使用 Select-Object 定义计算属性。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多