Contrary to common belief, PowerShell doesn’t just make up variables whenever it feels like it. Just a few years ago, I would have swore it did though. Take this script as example:
Get-ChildItem \\SERVER\SHARE\ -recurse -file | get-acl | Where-Object {$_.Owner -match "Joseph" }
We start by recursively listing every file on our share. These files are piped (|) to the get-acl command. Finally, we filter the results with the where-object command. Out of nowhere, we throw in $_.Owner variable! Now I have two questions – where did the $_ come from and how did the .Owner get added to it?
What Does $_. Mean in PowerShell?
As a simplified explanation, $_ symbolizes This. In the example above, you can think about the Where-Object segment like this: Where-Object {$THISFILE.Owner -match “Joseph” }. To quote this TechNet article,
$_ got its name because the underscore character resembles a pipeline character (|) lying on its side, implying that it contains whatever was piped in.
In essence, $_ is a dynamic variable storing the current information being piped to it! In the example above, $_ is the file. That clears things up a bit but…
Where Did $_.Owner Come From?
For right now, we are going to ignore the where-object section of the script above. If we ran Get-ChildItem \\SERVER\SHARE | Get-ACL, we would get an output like this:
In the screenshot above, you can see that Owner is a column in our output. It is literally a property (or member) of our output. So when we say $_.Owner, we are saying only to match “Joseph” against the Owner property of our output. This allows us to filter our data exactly how it is needed by looking at indivdual properties.
Nice Syntax You Got There, What are you – a Wizard?
Let’s dive into another example:
Get-ChildItem \\SERVER\SHARE | Where-Object {$_.CreationTime -lt (Get-Date)}
You will notice that if we simply run Get-ChildItem (without the where-object segment), our output looks like this:
In the first example, we are filtering based on the Creation Time ($_.CreationTime) of the file. However, our output of Get-Childitem does not include a Creation Time column. How did we achieve this magic? Easy – with the Get-Member command.
Earlier, we referred to the Owner property as a member. To see all members (properties) contained in the get-childitem output, we can type get-childitem | get-member
In the tiny output above, you will see a Property named CreationTime. You can use this property (or any other property listed) when you use $_.
I Can See Clearly Now!
As you can see, PowerShell isn’t the mysterious beast it appears to be. In this guide, we covered what $_. actually means in PowerShell and how you can find and choose properties to filter by. Personally, I use the trick often when dealing with Files and Active Directory. I covered this trick (plus others) in an hour long class a few months ago. You can download those notes for free right here.
On an kind of related note- PowerTips (one of the RSS feeds I subscribe to) had a pretty cool tip on PowerShell ISE. In the script pane, click on any cmdlet (such as Clear-Variable in the screenshot below). Then press F1 to quickly access the complete help file for that cmdlet! Pretty cool right?
To ensure you have the latest help files, set PowerShell to update your help files automatically.
I am a bit “late” this party, but you were able to explain this — to a complete PS “newb” by the way — where a myriad of other sites/blogs could not. Thank you for taking the time to write this out, I greatly appreciate it.
No problem at all! I appreciate the kind comment!
Fantastic. Do you have more material like this? You are a natural teacher.
Thank you Max! Feel free to look through the archives – quite a bit of material there.
I’ve visited dozens of websites trying to get a clear understanding of $_. and you explained it better than any of the sites I’ve tried. Thanks!
Not a problem Eric!
Awesome article.
Thank you Jose! Have a great day!