How to Use a PowerShell Foreach Loop

PowerShell

The PowerShell Foreach statement is useful when working with collections of items. It can be used to execute a command or a set of commands for each item in a collection. In this article, I will explain three different ways to use the Foreach keyword: the Foreach loop, the ForEach object cmdlet, and the ForEach method.

What is the PowerShell Foreach keyword for?

With PowerShell, there are different ways to process a collection of items. A collection could be retrieved from files using commands such as Get-Content for text files, Import-CSV for comma-separated value files, and Import-CliXML for hierarchical data stored in an XML file, etc. The collection could also be the result of a command execution or a filtered result using the Where-Object cmdlet.

When you need to perform an action against the members of this collection, you will be using the Foreach statement, which can be used as a loop, a cmdlet, or a method. In general, loops in PowerShell allow you to repeat a command or a set of commands until a condition is met.

If you use a Foreach loop, the operations will repeat until all items in the collection are processed. This reduces the size of the code and makes it more readable.

How to use a PowerShell Foreach loop

A PowerShell Foreach loop will move through the items in a collection and execute a command or a set of commands for each of them. The syntax you need to use is pretty simple.

Syntax

A PowerShell Foreach loop starts with the keyword followed by parenthesis with two variables: One for the collection and one for the current item that is being processed. The item variable is automatically created and assigned the value of the next item in the array before each iteration of the loop until all items are processed.

foreach ($<item> in $<collection>){<statement list>} 

At the end of the loop, the variable is not removed and contains the last processed item. The syntax continues with a script block containing a command or a list of commands which are executed against each item in the collection.

PowerShell Foreach loop examples

To demonstrate how to use a Foreach loop, let’s take the following example: We will take three services – WinRM, Spooler, and BITS providing information about the Display name, Service name, Status, and Start type. Display name will be on a separate line to simulate multiple commands being executed.

Without using any loop, the script would look like this:

# Service: WinRM
$ServiceWinRM = Get-Service -Name WinRM
Write-Host Processing Service: $ServiceWinRM.DisplayName -BackgroundColor DarkRed
Write-Host Service Name: $ServiceWinRM.Name is with status: $ServiceWinRM.Status and start type: $ServiceWinRM.StartType -BackgroundColor DarkGreen

# Service: Spooler
$ServiceSpooler = Get-Service -Name Spooler
Write-Host Processing Service: $ServiceSpooler.DisplayName -BackgroundColor DarkRed
Write-Host Service Name: $ServiceSpooler.Name is with status: $ServiceSpooler.Status and start type: $ServiceSpooler.StartType -BackgroundColor DarkGreen

# Service: BITS
$ServiceBITS = Get-Service -Name BITS
Write-Host Processing Service: $ServiceBITS.DisplayName -BackgroundColor DarkRed
Write-Host Service Name: $ServiceBITS.Name is with status: $ServiceBITS.Status and start type: $ServiceBITS.StartType -BackgroundColor DarkGreen 

This script provides the following result:

The result of our script without using a PowerShell Foreach loop
The result of our script without using a Foreach loop

If we use this initial example and modify it using the Foreach loop syntax, our code would look like this:

$serviceList = Get-Service -Name 'WinRM', 'Spooler', 'BITS'
foreach ($service in $serviceList) {
    Write-Host Processing Service: $service.DisplayName -BackgroundColor DarkRed
    Write-Host Service Name: $service.Name is with status: $service.Status and start type: $service.StartType -BackgroundColor DarkGreen
} 

By following the syntax of a Foreach loop, the variable containing the collection of services is named ‘serviceList’. The variable containing the current item that is being processed is named ‘service’.

Here’s what happens when we run this example in PowerShell:

  • On the first iteration, the variable ‘service’ is created and assigned the value of ‘WinRM’. Then it processes the script block providing information about Display Name on the first line, then Name, Status, and Start type on the second line.
  • On the next iteration, the variable is assigned the value of the second item in the collection – Spooler, and the process is repeated.
  • Finally, the variable ‘service’ is assigned with the value of service ‘BITS’. The script block is executed and the loop completes as all of the items in the collection are processed.
We run our script with a Foreach loop
We run our script with a Foreach loop

As we explained, the variable containing the currently processed item in the collection is being created on the first iteration of the loop. It remains available once the loop completes.

the variable containing the currently processed item in the collection remains available once the PowerShell Foreach loop completes
The variable containing the currently processed item in the collection remains available once the loop completes

How to use the PowerShell Foreach-Object cmdlet

Another way to process items in a collection is to use the PowerShell Foreach-Object cmdlet. There’s often some confusion about this command as it has an alias with Foreach, which looks like the loop statement covered in the previous section.

However, it is quite easy to differentiate the two of them: The Foreach loop is always at the beginning of the statement, while the Foreach alias appears after a pipeline symbol, processing the collection coming through the pipe.

The Foreach-Object command also has another alias which you may see here and there – %. The general rule in PowerShell is to avoid using aliases in your code as it makes it harder to read and could lead to confusion. Aliases can be handy to save some time while typing, but be mindful when you are writing your code and try to make it more readable for the next person reading it.

The PowerShell Foreach-object cmdlet has two aliases
The PowerShell Foreach-object cmdlet has two aliases

Syntax

The Foreach-Object cmdlet processes the objects send through the pipeline using the following (simplified) syntax:

<collection> | Foreach-Object -Process {<statement list>} 

Items from the collection are sent through the pipeline one after the other, and they’re processed in the script block of the Process parameter. There could be one or more lines of code.

Again, as in a Foreach loop, we have a variable containing the current item that is being processed. This time, though, it is a built-in variable (- $PSItem or $_) that’s only available until the pipeline is completed.

PowerShell Foreach-Object cmdlet examples

If we keep the same example as before with the three services WinRM, Spooler and BITS, here’s how our code would look like if we use the Foreach-Object cmdlet:

Get-Service -Name 'WinRM', 'Spooler', 'BITS' | ForEach-Object -Process {
    Write-Host Processing Service: $_.DisplayName -BackgroundColor DarkRed
    Write-Host Service Name: $_.Name is with status: $_.Status and start type: $_.StartType -BackgroundColor DarkGreen
} 
We get the same end result by using a the PowerShell Foreach-Object cmdlet
We get the same end result by using a the Foreach-Object cmdlet

The result is the same as in the previous examples. Here we are using the built-in variable ‘$_’, but it would be the same if we used ‘$PSItem’ as they are interchangeable.

Get-Service -Name 'WinRM', 'Spooler', 'BITS' | ForEach-Object -Process {
    Write-Host Processing Service: $PSItem.DisplayName -BackgroundColor DarkRed
    Write-Host Service Name: $PSItem.Name is with status: $PSItem.Status and start type: $PSItem.StartType -BackgroundColor DarkGreen
} 
We get the same result if we use the built-in variable '$PSItem'
We get the same result if we use the built-in variable ‘$PSItem’

In our scenario, the script block in the Process parameter of our Foreach-Command example is executed as many times as new objects are sent through the pipeline. There are also two parameters that you may find useful – Begin and End. They are executed only once at the beginning of the processing and after the processing is completed.

These two parameters are useful if you would like to set the ground for the execution of the collection. For example, at the beginning of your script, you may want to remove old log files, create new log files, set connections, provide user-friendly messages, etc. At the end of it, you may also want to clear big variables, close connections, provide messages, etc.

Here’s how the syntax you need to use with these two parameters:

<collection> | Foreach-Object -Begin {<statement list>} -Process {<statement list>} -End {<statement list>}

In the context of our current example, let’s provide some start and end messages that include the current date and time in dark yellow color for readability:

Get-Service -Name 'WinRM', 'Spooler', 'BITS' | ForEach-Object -Begin { 
    Write-Host Starting Foreach-Object processing -BackgroundColor DarkYellow
} -Process {
    Write-Host Processing Service: $_.DisplayName -BackgroundColor DarkRed
    Write-Host Service Name: $_.Name is with status: $_.Status and start type: $_.StartType -BackgroundColor DarkGreen
} -End {
    Write-Host Completed Foreach-Object processing -BackgroundColor DarkYellow
} 
We've added start and end messages that include the current date and time
We’ve added start and end messages that include the current date and time

How to use the PowerShell ForEach method

The ForEach method is another alternative you can use to process a collection of objects with PowerShell. Here’s how it works.

Syntax

The ForEach method uses the following syntax:

<$collection>.ForEach ({<statement list>})

The PowerShell ForEach method processes all items in a collection until completion. Again, as with the Foreach-Object cmdlet, you are referring to the current item in the collection using the built-in variables ‘$_’ or ‘$PSItem’.

PowerShell ForEach method example

If we apply the ForEach method to our previous example, here’s how the syntax would look like:

$serviceList = Get-Service -Name 'WinRM', 'Spooler', 'BITS'
$serviceList.ForEach({
    Write-Host Processing Service: $_.DisplayName -BackgroundColor DarkRed
    Write-Host Service Name: $_.Name is with status: $_.Status and start type: $_.StartType -BackgroundColor DarkGreen
}) 
As you can see, we get the same results as before with the ForEach method
PowerShell ForEach method example

As you can see, we get the same results as before.

Conclusion

In this article, I have covered three different ways to use the Foreach statement in PowerShell, including the Foreach loop, the ForEach-object cmdlet, and the ForEach method. To go further, you can check out our previous article about using the PowerShell ForEach Parallel option, as well as our general article on how to use PowerShell For Loop, While Loop, and other loops.