【问题标题】:powershell Get-ChildItem result in arraypowershell Get-ChildItem 结果为数组
【发布时间】:2021-08-05 09:01:02
【问题描述】:
(Get-ChildItem -File -Recurse -Path $path).Fullname 返回全名数组
(Get-ChildItem -File -Recurse -Path $path).Name 返回文件名数组
但
(Get-ChildItem -File -Recurse -Path $path).Length 只返回一个值——元素个数
问题 - 如何获取文件长度数组的结果?
【问题讨论】:
-
请允许我给你一个标准的建议给新手:如果你accept 一个答案,你将帮助未来的读者,向他们展示解决了你的问题的方法。要接受答案,请单击答案左侧大数字下方的大 ✓ 符号(您将获得 2 点声望)。如果您至少有 15 个声望点,您还可以投票给其他有用的答案(也可以选择接受的答案)。如果您的问题尚未解决,请提供反馈,或者,如果您自己找到了解决方案,请self-answer。
标签:
arrays
powershell
object
member-enumeration
【解决方案1】:
你得到的一个值确实是结果数组的长度 - Array 类有一个显式的Length property,它优先于属性枚举。
要从数组中的每个项目中获取单独的 Length 属性值,请通过管道连接到 Select-Object 或 ForEach-Object,如下所示:
Get-ChildItem -File -Recurse -Path $path |ForEach-Object -MemberName Length
# or
Get-ChildItem -File -Recurse -Path $path |Select-Object -ExpandProperty Length
【解决方案2】:
补充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 的回答中所指出的,type-native properties - 例如数组实例上的.Length - 优先于 所谓的 @您尝试执行的 987654323@ - 也就是说,您想要收集集合中 元素 的 .Length 属性值(数组;System.IO.FileInfo 实例输出的 @987654325 @),并将它们作为 ([object[]]) array 返回。
成员枚举的一个可能令人惊讶的方面是它应用了管道逻辑,因为它会根据情况返回一个标量,即如果集合恰好包含一个元素。
- 例如,
@(Get-Date).Year.GetType().Name 返回的是 System.Int32,而不是 Object[],表示返回的是整数而不是包含整数的(单元素)数组。
-
GitHub issue #6802 讨论这个问题。
成员枚举不仅方便,而且快速,因为它避免了PowerShell代码中的循环/枚举。
使用 ForEach-Object 或 Select-Object cmdlet,如 Mathias 的回答所示,绝对是 一个 功能但是 slow 解决方法 因为使用了 pipeline,因此在给定的情况下无法使用成员枚举,这对于输入来说是不必要的已经在内存中了。
因此,使用.ForEach() array method - 使用重载,您只需指定目标属性name ('Length') - 是一种简洁且性能更好的替代方案。
- 注意:与成员枚举不同,
.ForEach() 的返回值始终是一个集合,尽管不是数组:它是[System.Collections.ObjectModel.Collection[psobject]] 类型,但是在大多数情况下,它的行为类似于数组。[1]
[1] 与数组不同,这种类型的集合是可扩展的(您可以添加或删除元素)。由于元素类型为[psobject],每个元素通常不可见包裹在这种类型中;例如,42 -is [psobject] 是 $false,但 @(42).ForEach({ $_ })[0] -is [psobject] 是 $true。不幸的是,在种情况下,这种近乎不可见的包装器会导致不同的行为 - 请参阅 GitHub issue #5579。
【解决方案3】:
在您的示例中,您将获得结果数组的 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