Topic: Foreach-Object
Notice: This post is a part of the PowerShell Monday series — a group of quick and easy to read mini lessons that briefly cover beginning and intermediate PowerShell topics. As a PowerShell enthusiast, this seemed like a beneficial way to ensure those around me at work were consistently learning new things about Windows PowerShell. At some point, I decided I would share these posts here, as well. Here’s the PowerShell Monday Table of Contents.
Now that we have a basic understanding of the foreach language construct, we can move on to the ForEach-Object cmdlet. First, let’s consider the name of the cmdlet, as there are some similarities with some others. The noun — remember the verb-noun naming convention — is object. Let’s find all the commands with that same noun.
Get-Command -Noun Object | Select-Object CommandType,Name CommandType Name ----------- ---- Function Show-Object Cmdlet Compare-Object Cmdlet ForEach-Object Cmdlet Group-Object Cmdlet Measure-Object Cmdlet New-Object Cmdlet Select-Object Cmdlet Skip-Object Cmdlet Sort-Object Cmdlet Tee-Object Cmdlet Where-Object
If you’ve used some of the above commands, then you may recognize that many of these commands are used with the pipeline. This is to say, that we often send a command’s resulting objects to one of these commands.
In fact, take a look at the Get-Command, command we ran: We piped the objects created by Get-Command to the Select-Object cmdlet for further processing and filtering. That’s how we’ll use ForEach-Object, too; we’re always going to pipe to it.
Let’s begin with some conceptual examples of the ForEach-Object cmdlet. As we saw in a previous PSMonday, the first part of this example is the Microsoft help’s suggestion, and the second part of this example is how you’ll see me use the cmdlet.
<command> | ForEach-Object {<command_block>} <command> | ForEach-Object { <command_block> }
As we’ve stated before, always use full cmdlet names unless you’re using the command in a onetime use scenario. If you’re pounding out PowerShell commands with no intention of keeping them, then you can use either of the ForEach-Object aliases, as demonstrated below. This is important: foreach is an alias for the ForEach-Object cmdlet when it is used in a pipeline. When it’s not used in a pipeline, such as we saw in the last two weeks, it’s treated as the foreach language construct, and not as an alias for ForEach-Object. This can cause some confusion, and so it’s important to understand this distinction.
<command> | foreach { <command_block> } <command> | % { <command_block> }
Before we put things back on hold until next Monday, let’s take a look at a real-world example. Both of the following parts of this example do nearly the same thing. The difference is that one, the second half includes the string “Item: ,” and two, it uses the $PSItem automatic variable, instead of $_. This variable — regardless of which you use — represents the current object in the pipeline. $PSItem was introduced in PowerShell 3.0.
1,'string1',2,'string2' | ForEach-Object { Write-Output -InputObject $_ } Write-Output -InputObject '------' 3,'string3',4,'string4' | ForEach-Object { Write-Output -InputObject "Item: $PSItem" } 1 string1 2 string2 ------ Item: 3 Item: string3 Item: 4 Item: string4
In the above example, we sent four objects — two integers and two strings — down the pipeline to each of the ForEach-Object cmdlet examples. In looking at the first part of the example, $_ was 1 the first time the ForEach-Object cmdlet ran, it was ‘string1’, the second time the ForEach-Object cmdlet ran, 2 the third time, and ‘string2’ the final time the loop executed.
We’ll be back next week to help solidify how we use the ForEach-Object cmdlet.