下面的代码给了我一个PSCustomObjects数组,如何让它返回一个字符串数组?
$files = Get-ChildItem $directory -Recurse | Select-Object FullName | Where-Object {!($_.psiscontainer)}
(作为第二个问题,什么是psiscontainer部分?我从网上的例子中复制了它)
接受后编辑:两个很好的答案,希望我可以标记它们.已经给出了原始答案.
您只需要从对象中挑选出您想要的属性.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}
请注意,其中一个值正由变量捕获.它不会出现在输出管道中.
要获取可以使用的文件名字符串
$files = Get-ChildItem $directory -Recurse | Where-Object {!($_.psiscontainer)} | Select-Object -ExpandProperty FullName
该-ExpandProperty
参数允许您根据指定属性的类型返回对象.
进一步的测试表明,这不适用于V1,但从V2 CTP3开始,该功能已得到修复.
问题#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类型.