powershell Get-ChildItem 结果在数组中

问题描述

(Get-ChildItem -File -Recurse -Path $path).Fullname 返回全名数组 (Get-ChildItem -File -Recurse -Path $path).Name 返回文件名数组 但 (Get-ChildItem -File -Recurse -Path $path).Length 只返回一个值 - 元素的数量

问题 - 如何以文件长度数组的形式获取结果?

解决方法

您得到的一个值确实是结果数组的长度——Array 类有一个显式的 Length property,它优先于属性枚举。

要从数组中的每个项目中获取单独的 Length 属性值,请通过管道连接到 Select-ObjectForEach-Object,如下所示:

Get-ChildItem -File -Recurse -Path $path |ForEach-Object -MemberName Length
# or 
Get-ChildItem -File -Recurse -Path $path |Select-Object -ExpandProperty Length
,

在您的示例中,您将获得结果数组的 Length

Get-ChildItem -File 返回一个 System.IO.FileInfo 数组。因此,您需要获取(选择)数组中每个条目的 Length 属性。这是通过使用 Select-Object 或仅使用 select 来完成的:

Get-ChildItem -File -Recurse  -Path $path | Select-Object Length

它会给你一个包含文件长度的对象数组作为 Length 属性。您还可以选择多个属性:

Get-ChildItem -File -Recurse  -Path $path | Select-Object Name,Length
,

补充Mathias R. Jessen's helpful answer

tl;dr

使用 .ForEach() array method 可实现简洁高效的解决方案:

# Return the files' .Length property values as a collection.
(Get-ChildItem -File -Recurse -Path $path).ForEach('Length')

正如 Mathias 的回答所指出的那样,类型本机属性 - 例如数组实例上的 .Length - 优先于所谓的 >member enumeration 您尝试执行的操作 - 也就是说,您想要收集集合的 元素.Length 属性值(数组;{{ System.IO.FileInfo) 输出的 3}} 个实例,并将它们作为 ([object[]]) array 返回。

  • Get-ChildItem 讨论了这种情境歧义,并建议引入一个专用运算符,比如 %.,以便您可以明确请求任一常规属性访问或成员枚举。

成员枚举的一个可能令人惊讶的方面是它应用了管道逻辑,因为它根据情况返回一个标量,即如果集合恰好包含 一个元素

  • 例如,@(Get-Date).Year.GetType().Name 返回一个 System.Int32,而不是 Object[],表明返回的是一个整数而不是一个包含整数的(单元素)数组 .
  • GitHub issue #7445 讨论了这个问题。

成员枚举不仅方便,而且快速,因为它避免了PowerShell代码中的循环/枚举

使用 GitHub issue #6802ForEach-Object cmdlet,如 Mathias 的回答所示,绝对是功能性的 但缓慢变通办法,由于使用了不必要的管道,因此无法在给定情况下使用成员枚举用于内存中已满的输入。

因此,使用 Select-Object - 使用您只需指定目标属性 name ('Length') 的重载 - 是一个 简洁且性能更好的替代方案。

  • 注意:与成员枚举不同,.ForEach()返回值总是一个集合,尽管不是一个array:它是 [System.Collections.ObjectModel.Collection[psobject]] 类型,但是在大多数情况下它的行为类似于数组。[1]

[1] 与数组不同,这种类型的集合是可扩展的(您可以添加或删除元素)。由于元素类型为[psobject],每个元素通常不可见包裹在这种类型中;例如,42 -is [psobject]$false,但 @(42).ForEach({ $_ })[0] -is [psobject]$true。不幸的是,在情况下,这种几乎不可见的包装会导致不同的行为 - 请参阅.ForEach() array method