Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Select-Object to return a raw type (e.g. String) rather than PSCustomObject?

The following code gives me an array of PSCustomObjects, how can I get it to return an array of Strings?

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

(As a secondary question, what's the psiscontainer part for? I copied that from an example online)

Post-Accept Edit: Two great answers, wish I could mark both of them. Have awarded the original answer.

like image 701
Mark Ingram Avatar asked Mar 06 '09 12:03

Mark Ingram


1 Answers

You just need to pick out the property you want from the objects. FullName in this case.

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

Edit: Explanation for Mark, who asks, "What does the foreach do? What is that enumerating over?"

Sung Meister's explanation is very good, but I'll add a walkthrough here because it could be helpful.

The key concept is the pipeline. Picture a series of pingpong balls rolling down a narrow tube one after the other. These are the objects in the pipeline. Each stage of pipeline--the code segments separated by pipe (|) characters--has a pipe going into it and pipe going out of it. The output of one stage is connected to the input of the next stage. Each stage takes the objects as they arrive, does things to them, and sends them back out into the output pipeline or sends out new, replacement objects.

Get-ChildItem $directory -Recurse 

Get-ChildItem walks through the filesystem creating FileSystemInfo objects that represent each file and directory it encounters, and puts them into the pipeline.

Select-Object FullName 

Select-Object takes each FileSystemInfo object as it arrives, grabs the FullName property from it (which is a path in this case), puts that property into a brand new custom object it has created, and puts that custom object out into the pipeline.

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

This is a filter. It takes each object, examines it, and sends it back out or discards it depending on some condition. Your code here has a bug, by the way. The custom objects that arrive here don't have a psiscontainer property. This stage doesn't actually do anything. Sung Meister's code is better.

foreach {$_.FullName} 

Foreach, whose long name is ForEach-Object, grabs each object as it arrives, and here, grabs the FullName property, a string, from it. Now, here is the subtle part: Any value that isn't consumed, that is, isn't captured by a variable or suppressed in some way, is put into the output pipeline. As an experiment, try replacing that stage with this:

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

Actually try it out and examine the output. There are four values in that code block. None of them are consumed. Notice that they all appear in the output. Now try this:

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

Notice that one of the values is being captured by a variable. It doesn't appear in the output pipeline.

like image 195
dan-gph Avatar answered Sep 21 '22 09:09

dan-gph