【问题标题】:return array of objects from Get-ChildItem -Path从 Get-ChildItem -Path 返回对象数组
【发布时间】:2019-04-19 16:40:35
【问题描述】:

在 powershell 中,ls -R *.txt 将按目录递归列出文件,或者更好:

PS> Get-ChildItem -Path C:\Test -Name

日志

anotherfile.txt
Command.txt
CreateTestFile.ps1
ReadOnlyFile.txt

但是我如何将它输入到数组中呢?我想要一个文件(?)对象本身的数组,查看:

Get-ChildItem "C:\WINDOWS\System32" *.txt -Recurse | Select-Object FullName

https://stackoverflow.com/a/24468733/262852

我正在从这些类型的命令中寻找带有 powershell 的“文件”对象数组。

可能更好的语法:

Copy-Item -Filter *.txt -Path c:\data -Recurse -Destination C:\temp\text

但不是复制项目,我只想要一个对象,或者更确切地说,对象数组。不是文件的路径,也不是文件,但可能是 powershell 引用或指向文件的指针。

(现在阅读fine 手册。)

【问题讨论】:

  • get-ChildItem "C:\windows\system32" -include "*.txt" -Recurse 产生一个对象数组。
  • 我不确定你在这里得到什么。但是powershell会自动返回一个对象。您所要做的就是将其分配给一个变量。 $txtfiles = Get-ChildItem "C:\WINDOWS\System32" *.txt -Recurse | Select-Object FullName。在这种情况下,$txtfiles 将是一个数组对象。
  • @AdminOfThings 数组将包含System.IO.FileSystemInfo 类型的对象?好的,这就是我需要知道的。

标签: windows powershell file directory sysadmin


【解决方案1】:

tl;dr

  • 当您在变量(例如,
    $output = Get-ChildItem ...)中捕获 PowerShell 语句的输出时,如果有两个或更多,它会自动收集到一个数组中> 输出对象。

  • 为了确保数组总是被使用——即使只有一个单个no输出对象——使用@(...)(例如,
    $output = @(Get-ChildItem ...))


  • PowerShell cmdlet,例如Get-ChildItem,可以输出任意数量的对象。

    • Get-ChildItem 输出 [System.IO.FileInfo] 和/或 [System.IO.DirectoryInfo] 对象,具体取决于是否正在输出有关文件和/或目录的信息。

    • 确定给定 cmdlet 的输出对象类型

      • 运行,例如,(Get-Command Get-ChildItem).OutputType
      • 如果这不起作用,或者要查看特定调用的输出类型,请使用
        Get-ChildItem | Get-Member
      • Get-Help -Full Get-ChildItem 也应该显示一个 OUTPUTS 部分,online help 也是如此,尽管在 Get-ChildItem 的情况下它不太具体,因为 Get-ChildItem 也适用于文件系统以外的提供程序。李>
  • 输出到管道时,每个输出对象单独传递给管道中的下一个命令,通常是立即处理。

  • 输出在变量 ($var = ...)中被捕获时,以下逻辑适用:

    • 如果输出两个或更多个对象,它们将被收集在一个常规的 PowerShell 数组中,该数组的类型为 [object[]](即使实际元素具有特定类型)。
    • 如果输出一个对象,则按原样输出;也就是说,它没有包裹在一个数组中。
    • 如果输出 no 对象,则输出“数组值 null”[System.Management.Automation.Internal.AutomationNull]::Value,在大多数情况下其行为类似于 $null,并导致无可见输出 - 请参阅 @987654322 @了解详情。

因此,当在变量中捕获时,给定的命令可能按情况返回

  • 对象数组
  • 单个对象
  • “什么都没有”([System.Management.Automation.Internal.AutomationNull]::Value)

为确保给定命令的输出始终被视为数组,您有两种选择:

  • 使用@(...)array subexpression operator;例如

    • $fileSystemObjects = @(Get-ChildItem -Recurse -Filter *.txt)
  • 使用[array] 对目标变量进行类型约束(相当于[object[]],并且比[object[]] 更易于键入)。

    • [array] $fileSystemObjects = Get-ChildItem -Recurse -Filter *.txt

也就是说,在 PSv3+ 中,您通常不必担心给定变量是包含标量(单值)还是数组,因为标量可以隐式地被视为数组:您甚至可以在标量上调用.Count,并使用索引([0][-1]) - 有关详细信息,请参阅this answer

【讨论】:

  • 好的,感谢有关如何处理类型和数组的指针。我喜欢 Get-Member 命令行开关。
  • @Thufir;我的荣幸。您接受的答案会告诉您Get-ChildItem 返回的具体类型,这可能是您打算问的,但不是您确实问的。请考虑未来读者的观点。
  • 很公平,我感谢您的回答彻底。在这一点上,我有点过头了,但我希望能多次回到它:)
  • TL;DR 使用@(...) 确保输出始终被视为一个数组!
  • 好点,@xjcl - 请查看我的更新。
【解决方案2】:

Get-ChildItem "C:\test" -Recurse 将返回一个数组内的 FileInfo 和 DirectoryInfo 对象

我们可以在这里看到一个例子

Get-ChildItem "C:\test" -Recurse | %{
    $_.gettype()
}

返回

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     DirectoryInfo                            System.IO.FileSystemInfo
True     True     DirectoryInfo                            System.IO.FileSystemInfo
True     True     FileInfo                                 System.IO.FileSystemInfo
True     True     DirectoryInfo                            System.IO.FileSystemInfo

【讨论】:

  • 正是我需要知道的,谢谢。这是获取类型的标准习语吗?
  • 这个答案具有误导性,因为Get-ChildItem -Recurse 有时不返回数组。见 mklement0 的回答。
  • @orionelenzil 误导是一个强烈的词。他要一个答案,我给了他一个。我的答案适用于他想要的。他甚至在下面回复说谢谢,但这“在他头上”。有时并不总是需要或想要深入的解释。
  • 我不知道。如果c:\test 仅包含一个文件,则结果类型为System.IO.FileSystemInfo
  • 你可能是对的,“误导”这个词太强了。我之所以选择这个 nit,是因为这种特殊行为多次让我绊倒 - 我针对返回许多文件的搜索编写脚本,一切都很好,$x.Length 等于项目数等,但随后我的脚本在某处运行搜索只返回一个项目,现在我的代码中断了。 $x.Length 是返回的一个文件的文件大小,等等。
猜你喜欢
  • 2014-05-08
  • 1970-01-01
  • 2019-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-14
  • 1970-01-01
相关资源
最近更新 更多