Using the Foreach-Object Cmdlet

Looping Through a Collection of Objects

The ForEach-Object cmdlet provides a way to loop through - and perform an action on - each item in a collection. Keep in mind that, in many cases, you won’t need to use ForEach-Object; that’s because, by default, many cmdlets already work with all the items in a collection. For example, if you call the Get-Process cmdlet you’ll automatically get back information about all the processes running on your computer; you don’t have to use ForEach-Object to loop through the collection. (This is different than VBScript, where you typically do have to set up a For Each loop each time you need to get at all the items in a collection.)

On the other hand, there might be times when you need to do some additional formatting or make other modifications to the objects in a collection; in those cases, you typically will need to use ForEach-Object. For example, suppose you want to display a list of process names, but you’d like those names to be written in cyan. (Don’t worry: the Scripting Guys never pass judgment on the things you choose to do, or why you choose to do them.) This command will fail because the Write-Host cmdlet doesn’t know what to do with the data sent over the pipeline:

Get-Process | Write-Host $_.name -foregroundcolor cyan

To be more specific, you get back this error message:

At line:1 char:25
+ get-process | write-host  <<<< $_.name -foregroundcolor cyan Write-Host : The input object 
cannot be bound to any parameters for the command  either because the command does not 
take pipeline input or the input and its properties do not match any of the parameters 
that take pipeline input.

So what do you do in a situation like that? Why, you use ForEach-Object, of course:

Get-Process | ForEach-Object {Write-Host $_.name -foregroundcolor cyan}

This time around we retrieve the process information and pipe it to ForEach-Object instead of Write-Host. That’s because ForEach-Object knows exactly what to do with a collection of objects tossed across the pipeline: it’s going to loop through the collection and do something to each of those objects, one-by-one. And what will it do to those objects? That’s easy: ForEach-Object will carry out the commands enclosed in the curly braces; in this case, for each item in the collection we’ll use the Write-Host cmdlet to write the value of the Name property to the screen, and in cyan-colored text to boot.

Here’s what the console window will look like after the command has run:

ForEach-Object Aliases
  • foreach