当前位置:  开发笔记 > 运维 > 正文

如何让Select-Object返回原始类型(例如String)而不是PSCustomObject?

如何解决《如何让Select-Object返回原始类型(例如String)而不是PSCustomObject?》经验,为你挑选了3个好方法。

下面的代码给了我一个PSCustomObjects数组,如何让它返回一个字符串数组?

$files = Get-ChildItem $directory -Recurse | Select-Object FullName | Where-Object {!($_.psiscontainer)}

(作为第二个问题,什么是psiscontainer部分?我从网上的例子中复制了它)

接受后编辑:两个很好的答案,希望我可以标记它们.已经给出了原始答案.



1> dan-gph..:

您只需要从对象中挑选出您想要的属性.FullName在这种情况下.

$files = Get-ChildItem $directory -Recurse | Select-Object FullName | Where-Object {!($_.psiscontainer)} | foreach {$_.FullName}

编辑: Mark的解释,谁问,"foreach做了什么?枚举的内容是什么?"

Sung Meister的解释非常好,但我会在这里添加一个演练,因为它可能会有所帮助.

关键概念是管道.想象一系列乒乓球一个接一个地滚下一根细管.这些是管道中的对象.管道的每个阶段 - 由管道(|)字符分隔的代码段 - 都有一个管道进入它,管道从它出来.一级的输出连接到下一级的输入.每个阶段在对象到达时对其进行处理,对它们执行操作,并将它们发送回输出管道或发送新的替换对象.

Get-ChildItem $directory -Recurse

Get-ChildItem遍历文件系统,创建表示它遇到的每个文件和目录的FileSystemInfo对象,并将它们放入管道中.

Select-Object FullName

Select-Object在每个FileSystemInfo对象到达时获取它,从中获取FullName属性(在这种情况下是一个路径),将该属性放入它创建的全新自定义对象中,并将该自定义对象放入管道中.

Where-Object {!($_.psiscontainer)}

这是一个过滤器.它需要每个对象,检查它,并将其发回或根据某些条件丢弃它.顺便说一句,这里的代码有一个bug.到达此处的自定义对象没有psiscontainer属性.这个阶段实际上并没有做任何事情.Sung Meister的代码更好.

foreach {$_.FullName}

Foreach,其长名称为ForEach-Object,在它到达时抓取每个对象,并在此处从中获取FullName属性(字符串).现在,这里是一个微妙的部分:任何未消耗的值,即未被变量捕获或以某种方式被抑制的值,都会被放入输出管道中.作为一项实验,尝试用以下方法替换该阶段:

foreach {'hello'; $_.FullName; 1; 2; 3}

实际上尝试一下并检查输出.该代码块中有四个值.它们都没有消耗掉.请注意,它们都出现在输出中.现在试试这个:

foreach {'hello'; $_.FullName; $ x = 1; 2; 3}

请注意,其中一个值正由变量捕获.它不会出现在输出管道中.


更好的解决方案是使用select-object -expand FullName

2> Steven Muraw..:

要获取可以使用的文件名字符串

$files = Get-ChildItem $directory -Recurse | Where-Object {!($_.psiscontainer)} | Select-Object -ExpandProperty FullName

-ExpandProperty参数允许您根据指定属性的类型返回对象.

进一步的测试表明,这不适用于V1,但从V2 CTP3开始,该功能已得到修复.



3> dance2die..:

问题#1

我删除了"select-object"部分 - 它是冗余的并且在"foreach"之前移动"where"过滤器,与dangph的答案不同- 尽快过滤,以便您只处理下一步要处理的部分内容管道.

$files = Get-ChildItem $directory -Recurse | Where-Object {!$_.PsIsContainer} | foreach {$_.FullName}

该代码片段基本上是读取的

以递归方式获取所有文件的所有文件的完整路径(Get-ChildItem $ directory -Recurse)

过滤掉目录(Where-Object {!$ _.PsIsContainer})

仅返回完整文件名(foreach {$ _.FullName})

将所有文件名保存到$ files中

请注意,对于foreach {$ _.FullName},在powershell中,返回脚本块({...})中的最后一个语句,在本例中为$ _.字符串类型的FullName

如果你真的需要获得一个原始对象,那么在删除"select-object"之后你不需要做任何事情.如果您要使用Select-Object但想要访问原始对象,请使用"PsBase",这是一个完全不同的问题(主题) - 有关详细信息,请参阅" PSBASE,PSEXTENDED,PSADAPTED和PSOBJECT的内容是什么? "那个主题

对于问题#2

并且还通过!$ _过滤.PsIsContainer意味着您要排除容器级别对象 - 在您的情况下,您在FileSystem提供程序上执行Get-ChildItem(您可以通过Get-PsProvider查看PowerShell提供程序),因此容器是DirectoryInfo(文件夹)

PsIsContainer在不同的PowerShell提供者下意味着不同的东西; 例如)对于Registry提供者,PsIsContainer的类型为Microsoft.Win32.RegistryKey 试试这个:

>pushd HKLM:\SOFTWARE
>ls | gm

[更新]以下问题:foreach做了什么?什么是枚举? 为了澄清,"foreach"是"Foreach-Object"的别名你可以找到,

get-help foreach

- 要么 -

get-alias foreach

现在在我的回答中,"foreach"枚举了从前一个管道返回的FileInfo类型的每个对象实例(它具有已过滤的目录). FileInfo有一个名为FullName的属性,这就是"foreach"枚举的内容.
并且您通过名为"$ _"的特殊管道变量引用通过管道传递的对象,该变量在"foreach"的脚本块上下文中属于FileInfo类型.

推荐阅读
吻过彩虹的脸_378
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有