PowerShell for N00bs 4: More Properties than a Monopoly Board

We used Select-Object -Property to, well, select properties (after all, PowerShell is trying to move away from obscure abbreviations and truncated names.)  How do we know what properties exist?

Get-Member. We covered this in N00bs 2.

Get-Member gets the ... class members of a PowerShell object.  Again, clear names make for clumsy blogs.  To review, class members are methods (functions) and properties (data fields) that the PowerShell object.  It's called a class member, but belongs to an object because an object is an instance of a class. 

Let's see what properties a folder has:

PSH> Get-Item c:\

That's the folder.  Now, let's get the members:

PSH> Get-Member -InputObject (Get-Item c:\)

And let's only look at the properties:

PSH> gm -i (gi \) -m *property

   TypeName: System.IO.DirectoryInfo

Name MemberType Definition
---- ---------- ----------
Mode CodeProperty System.String Mode{get=Mode;}
PSChildName NoteProperty System.String PSChildName=C:\
PSDrive NoteProperty System.Management.Automation.PSDriveInfo PS...
PSIsContainer NoteProperty System.Boolean PSIsContainer=True
PSParentPath NoteProperty System.String PSParentPath=
PSPath NoteProperty System.String PSPath=Microsoft.PowerShell.C...
PSProvider NoteProperty System.Management.Automation.ProviderInfo P...
Attributes Property System.IO.FileAttributes Attributes {get;set;}
CreationTime Property System.DateTime CreationTime {get;set;}
CreationTimeUtc Property System.DateTime CreationTimeUtc {get;set;}
Exists Property System.Boolean Exists {get;}
Extension Property System.String Extension {get;}
FullName Property System.String FullName {get;}
LastAccessTime Property System.DateTime LastAccessTime {get;set;}
LastAccessTimeUtc Property System.DateTime LastAccessTimeUtc {get;set;}
LastWriteTime Property System.DateTime LastWriteTime {get;set;}
LastWriteTimeUtc Property System.DateTime LastWriteTimeUtc {get;set;}
Name Property System.String Name {get;}
Parent Property System.IO.DirectoryInfo Parent {get;}
Root Property System.IO.DirectoryInfo Root {get;}
BaseName ScriptProperty System.Object BaseName {get=$this.Name;}

Now, what is contained in each?  We could expand each, but why?  Let's talk about loops.

Firstly, let's save the 'Get-Item' as a variable so we don't have to keep getting the same data over and over:

PSH> $folder = gi \

Next, let's look the data:

PSH> gm -i $folder -m *property | % { $name= $_.name; @{$name= $_.$name; } } | fl

Okay, lots of shortcuts here.  Here's a glossary:

gm  Get-Member
-i  -InputObject
-m  -MemberType
%   Foreach-Object
$_  Placeholder (see below.)
@{} Output results as name/value pairs (to be elaborated in later post.)
fl  Format-List

Let's take a walkthrough:

We're getting the list of properties, then looping over that list.  For each element of the list (shown in the table above), we are interested only in the 'Name' value.

Let's look at looping a little closer.  $_ is the placeholder.  We're looking at each element of the list in turn, right?  Which element are we looking at right now?  PowerShell takes the current one and makes it available to us as $_.

So, for the first property, the 'mode' property, we take only the name, 'mode.'  $folder.mode is the mode data ("d--hs"), just like $folder.attribute is the attribute data ("Hidden, System, Directory")

Next, we do a bit of syntactical sugar, primarily for formatting.  We could have just output "$name = $($folder.$name)", but that outputs strings, not objects.  This means the data is flattened to strings.  Instead @{} allows us to output name/value pairs.

PSH> gm -i $folder -m *property | % { $name = $_.Name; @{$name = $folder.$name; } }

Name Value
---- -----
Mode d--hs
PSChildName C:\
PSDrive C
PSIsContainer True
PSParentPath
PSPath Microsoft.PowerShell.Core\FileSystem::C:\
PSProvider Microsoft.PowerShell.Core\FileSystem
Attributes Hidden, System, Directory
CreationTime 4/21/2009 11:01:15 PM
CreationTimeUtc 4/22/2009 6:01:15 AM
Exists True
Extension
FullName C:\
LastAccessTime 8/25/2009 3:37:54 PM
LastAccessTimeUtc 8/25/2009 10:37:54 PM
LastWriteTime 8/25/2009 3:37:54 PM
LastWriteTimeUtc 8/25/2009 10:37:54 PM
Name C:\
Parent
Root C:\
BaseName C:\ 

As an example of what we mean:

PSH> gm -i $folder -m *property | % { $name = $_.Name; @{$name = $folder.$name; } } | fl

Name : Mode
Value : d--hs

(etc.)

Now, this isn't as useful as we'd like because that syntactical sugar.  We're outputting a list of name/value pairs, instead of a single data object.  A future post will expand on this.

To review, we learned a few things:

  • Get-Member allows us to inspect an object's class members.
  • We can specify MemberType to filter Get-Member's output.
  • Foreach-Object loops over each item in a list, such as an object's properties.