PowerShell ForEach Loop, ForEach-Object Cmdlet: Beginner’s Guide

Loops are an essential part of any programming or scripting language, allowing you to repeat a task multiple times without rewriting the code. In PowerShell, there are several looping constructs available, with the ForEach loop and ForEach-Object cmdlet being two of the most commonly used options. They allow you to iterate through a collection of items and perform a specific action on each item in the collection.

In this beginner’s guide, we will cover the basics of using ForEach loops and the ForEach-Object cmdlet in PowerShell. We’ll look at the syntax, walk through examples, explain how to use these cmdlets to work with collections of objects, and highlight the key differences between these two loop constructs. Whether you’re just starting out with PowerShell or looking to level up your scripting skills, learning how to effectively leverage ForEach loops and the ForEach-Object cmdlet will enable you to write more efficient and powerful scripts. Let’s dive in!

PowerShell ForEach Loop Overview

Loops allow you to iterate through a collection of items and repeat an operation for each item. They are essential for automating repetitive tasks in PowerShell. The ForEach loop in PowerShell allows you to iterate over a collection of objects, such as an array, a list of files, a set of user accounts, or a list of items.

Syntax

The syntax for the ForEach cmdlet is as follows:

ForEach (item in collection) {
    # code to execute on each item
}

The Foreach loop starts with the keyword “ForEach” followed by parenthesis with a collection to iterate. Then, the scriptblock to execute is wrapped inside curly brackets {}.

‘ForEach’ Loop with An Array

Here is a simple example of how to use the ForEach loop in PowerShell to iterate over an array:

$items = 1,2,3,4,5

ForEach ($item in $items)
{
   Write-Host "Item: $item"
}

This loop iterates over an array of numbers (The code block inside the loop – the statements between the curly braces) is executed for each iteration of the loop) and prints each number to the console. This will output the following:

Item: 1
Item: 2
Item: 3
Item: 4
Item: 5

Here is another example of looping through an array in PowerShell:

# Define an array
$fruits = @("Apple", "Banana", "Cherry", "Date")

# Loop through the array using ForEach
foreach ($fruit in $fruits) {
    Write-Output $fruit
}

ForEach Loop with a Collection Of Objects

You can also use the ForEach loop to iterate over the properties of an object:

#Object
$Employee = [pscustomobject] @{
    Name = "Shan Mathew"
    Designation = "IT Manager"
    Country = "United States"
}

#Get All Properties of the Object
Foreach ($Property in $Employee.PSObject.Properties)
{
    Write-Host "$($Property.Name): $($Property.Value)"
}

This will output the following:

Name: Shan Mathew
Designation: IT Manager
Country: United States

You can also use the ForEach loop to perform actions on each item in a list of objects, such as files or folders. For example:

#Get All Files from a Folder
$Files = Get-ChildItem "C:\Temp" | Where { !$_.PSIsContainer }

#Print Each File Name in the Console
ForEach ($File in $Files) {
    Write-host $File.Name
}

In this example, the Get-ChildItem cmdlet is used to get a list of all the files in the C:\Temp directory, and the ForEach loop iterates over the list of files and prints the name of each file to the console. Please note that the loop executes only when the collection is not null. The loop completes when all of the items in the collection are processed – Unless there is an error inside the script block.

powershell foreach

Nested “ForEach” Loop in PowerShell

A nested ForEach loop in PowerShell refers to putting one ForEach loop inside another ForEach loop. This allows you to iterate through multiple collections or levels of objects. For every iteration of the outer loop, the entire inner loop will complete its iterations.

The basic structure of the nested ForEach loop is:

foreach ($outerItem in $outerCollection) {
    # Code for outer loop...

    foreach ($innerItem in $innerCollection) {
        # Code for inner loop...
    }
    
    # More code for outer loop, if necessary...
}

Let’s take a simple example: You want to create a simple multiplication table for numbers 1 to 5, from 1 to 10, let’s use PowerShell nested loop:

# Outer loop iterates from 1 to 5
ForEach ($i in 1..5) {

  # Inner loop iterates from 1 to 10  
  ForEach ($j in 1..10) {

    # Calculate and output multiplication result
    $result =  $j * $i
    Write-Output "$j x $i = $result"
  }

  # Add a blank line after each outer loop iteration
  Write-Output ""
}

Iterate through Files in Folders using Nested ForEach Loop

Let’s consider this real-world scenario: You want to list all files inside each folder. In this case:

  1. The outer loop will iterate over each folder.
  2. For every folder that the outer loop selects, the inner loop will iterate over each file within that folder.
# Get All 1st-level Sub-folders from a folder
$Folders = Get-ChildItem -Path "C:\Temp" -Directory

# Outer loop to iterate over each folder
ForEach ($Folder in $Folders) {
    Write-host -f Magenta "Processing Files in Folder: $Folder"

    # Get all files in the current folder
    $Files = Get-ChildItem -Path $Folder.FullName -File

    # Nested loop to iterate over each file in the current folder
    foreach ($File in $Files) {
        Write-Host -f Cyan "Processing File: " $File.FullName
        
        # Add any additional processing for each file if necessary        
    }
}

Nested loops are useful in scenarios where you have hierarchically structured data or tasks. As seen in the example, folders contain files. So, for each folder, you have to perform actions on multiple files inside it.

How to filter in collection within ForEach Loop?

Here is an example of how to filter items in a collection within a ForEach loop in PowerShell: You have a list of employees with their ages. You want to list out only those employees who are above a certain age, let’s say 30.

# Define a collection of employees with their ages
$employees = @(
    @{Name="John"; Age=25},
    @{Name="Robert"; Age=35},
    @{Name="Michael"; Age=29},
    @{Name="David"; Age=40}
)

# Loop through the collection using ForEach
foreach ($employee in $employees) {
    # Check if the age of the current employee is greater than 30
    if ($employee.Age -gt 30) {
        Write-Output ("Name: $($employee.Name), Age: $($employee.Age)")
    }
}

In this script, we use a ForEach loop to iterate over the $employees collection. Within the loop, the if condition filters out employees whose age is greater than 30, and then it displays the relevant details for those employees.

Here is another real-world scenario to filter collections in loop: Filter files by extension in the following example.

$files = Get-ChildItem .\documents

ForEach ($file in $files) {
  if ($file.Extension -eq ".txt") {
    Write-Output $file.Name
  }
}

PowerShell ForEach-Object cmdlet

The ForEach-Object cmdlet allows you to perform an action on each object in a collection of input objects. Unlike the ForEach statement in PowerShell, It uses the pipeline as its input. The syntax for the ForEach-Object cmdlet is as follows:

$Collection | ForEach-Object {
    # code to execute on each item
}

PowerShell 1..10 ForEach

Here is an example of using ForEach-Object to loop over the range of numbers from 1 to 10:

#Loop between 1 to 10 numbers
1..10 | ForEach-Object {
    Write-host $_
}

This prints the numbers between 1 and 10 on the screen. The ForEach-Object is often used in conjunction with the Where-Object cmdlet to filter the objects in the collection before performing the action. ForEach-Object can be used with any type of object, including arrays, lists, strings, etc. Here are some examples:

  • Get a list of all items from a directory – Get-ChildItem -Path "C:\Temp" | ForEach-Object { $_.Name }
  • Get a list of all the processes running on a computer – Get-Process | ForEach-Object { $_.ProcessName }
  • Convert all the strings in a list to uppercase – "One", "Two", "Three" | ForEach-Object { $_.ToUpper() }

Modifying Items Within a “ForEach-Object” Loop

Here is a how to modify items in a string array using the ForEach-Object loop in PowerShell:

# Define a String Array
$names = @("John", "Robert", "Michael", "David")

# Modify items in the String Array using ForEach-Object
$modifiedNames = $names | ForEach-Object {
    "Mr. $_"
}

# Display the modified array
$modifiedNames

As shown above, The ForEach-Object allowed us to easily modify each item in the array by operating on the automatic variable $_ in the loop – which denotes the current object in the loop iteration. This is a simple way to manipulate collections in PowerShell.

ForEach-Object with -Begin and -End parameters

The -Begin and -End parameters allow you to specify script blocks that are executed before and after the iteration through the collection, respectively. For example, let’s iterate through each file in a folder:

Get-ChildItem "C:\Temp" | Where { !$_.PSIsContainer } | ForEach-Object {
  Write-Host "Processing file $($_.Name)"
} -Begin {
  Write-Host "Start processing files"
} -End {
  Write-Host "Finished processing files"
}

In this example, the script block specified with the -Begin parameter is executed before the iteration starts, and the script block specified with the -End parameter is executed after the iteration is completed.

You can also use the ForEach loop to perform actions on each item in a list of objects, such as files or folders.

Parallel Processing With The ‘ForEach-Object’ Cmdlet

Starting from PowerShell 7, the ForEach-Object cmdlet provides a -Parallel parameter that allows you to process items concurrently. Here’s an example demonstrating the use of parallel processing with the ForEach-Object cmdlet:

Scenario: You have a list of URLs, and you want to fetch the status of each URL concurrently to save time.

# List of URLs to check
$URLS = @(
    "http://example.com",
    "http://example.org",
    "http://example.net",
    "http://example.edu",
    "http://example.tk",
    "http://example.biz",
    "http://example.ai",
    "http://example.uk",
    "http://example.app",
    "http://example.blog",
    "http://example.tech",
    "http://example.br"
)

# Using ForEach-Object with -Parallel to check URLs concurrently
$Results = $URLS | ForEach-Object  -Parallel {
    #Validate the URL
    Try { 
        $Response = Invoke-WebRequest -Uri $_ -Method Head 
    }
    Catch {
        $Response = $null
    }
    If ($Response) {
        Return "$url - $($response.StatusCode)"
    } Else {
        Return "$url - Unreachable"
    }
} -ThrottleLimit 10  # Set a limit on the maximum number of parallel tasks

# Display results
$Results

This script will return the status of each URL much faster than processing them one by one.

ForEach Loop VS ForEach-Object cmdlet in PowerShell

In PowerShell, the ForEach loop and the ForEach-Object cmdlet are both used to iterate through a collection of objects, but they work slightly differently. When you place ForEach statement at the beginning of the line (E.g., ForEach ($item in $items) {}), it is a traditional loop construct that allows you to execute a block of code for each element in an array or collection.

The ForEach-Object cmdlet, on the other hand, is a cmdlet that is designed to work with the PowerShell pipeline. It takes input from the pipeline, performs an operation on each object, and passes the results down the pipeline. Here’s an example of using the ForEach-Object cmdlet: (E.g., Get-ChildItem | ForEach-Object { Write-Host $_.Name }). The ForEach keyword can also be piped to, because it’s also an alias for ForEach-Object. But the reverse is not possible!

PowerShell ForEach vs. ForEach-Object: Which one to use?

Now that we’ve covered the similarities and differences between foreach and foreach-object, you might be wondering which one to use in your PowerShell scripts. The answer depends on your specific scenario and requirements.

If you already have a collection of objects and just need to iterate through them, ForEach is probably the way to go. If you’re working with pipeline input or need more flexibility in how you handle input, ForEach-Object may be a better choice.

Import CSV File and Iterate through Each Line with PowerShell ForEach Statement

Let’s see a practical example of importing data from a CSV file. Say you have a CSV file in “C:\Data\Users.csv” with the below content:

Name,Age,Occupation
John,25,Engineer
Jane,30,Doctor
Doe,28,Artist

Let’s use a PowerShell ForEach Loop to read through a CSV File Rows:

# Import CSV file
$CSVData = Import-Csv -Path "C:\Data\Users.csv"

# Loop through each row in the CSV
ForEach ($user in $CSVData) {
    Write-Output ("Name: $($user.Name), Age: $($user.Age), Occupation: $($user.Occupation)")
}

In the previous example, we have used the ForEach statement. This time, let’s rewrite it using ForEach-Object cmdlet:

# Import CSV file
$csvData = Import-Csv -Path "C:\Data\Users.csv"

# Loop through each row in the CSV
$CSVData | ForEach-Object {
    Write-Output ("Name: $($_.Name), Age: $($_.Age), Occupation: $($_.Occupation)")
}

Similarly, You can loop through lines in a text file using the below script:

#Get Content from Text File
$ServersList = Get-Content "C:\Data\ServersList.txt"

#Read Text file line by line
Foreach ($server in $ServersList) {
	Try {
        Test-Connection -ComputerName $server -Count 1 -ErrorAction stop
		Write-Output "$server - OK"
	}
	Catch {
		Write-Output "$server - $($_.Exception.Message)"
	}
}

This PowerShell loops through the server list in the given text file and tries to ping the server.

Break ForEach Loop and ForEach-Object cmdlet in PowerShell

The break keyword can be used to exit a ForEach or ForEach-Object loop prematurely in PowerShell.

How to Break ForEach Loop in PowerShell?

The ForEach statement allows you to iterate over a collection of items and perform an action on each item. But what if you need to break out of the loop early? To exit a foreach loop early in PowerShell, you can use the break keyword. Here’s an example:

$Array = 1..10
Foreach($Val in $Array){
    #Stop at 5
    if($val -eq 5){
        break
    }
    Write-Host "Value: $val"
}

Output:

Value: 1
Value: 2
Value: 3
Value: 4

In the example above, the foreach loop will iterate through the elements of the $array array. When the loop reaches the element with a value of 5, the break keyword will be encountered, causing the loop to exit immediately.

Break ForEach-Object cmdlet Iteration

To break out of a ForEach-Object loop in PowerShell, you can use the break keyword. The break keyword immediately exits the loop and continues execution of the script after the loop. Here is an example of using break in a ForEach-Object loop:

#Get All running processes
$Processes = Get-Process
$Counter = 1

#Iterate through each process
$Processes | ForEach-Object {
  Write-host "Processing Item $Counter of $($Processes.count)"
  if ($_.Name -eq "notepad") {
    Write-Host "Found Notepad process and exiting from the Loop!"
    break
  }
  $Counter++
}
Write-Host "Finished processing processes"

In this example, the script gets a list of processes using Get-Process and iterates over each process using ForEach-Object. If the name of the process is “notepad”, a message is displayed, and the break keyword is used to exit the loop. The script then continues execution after the loop.

break PowerShell ForEach Loop

Skipping an Element with “Continue” in PowerShell ForEach method

The continue keyword to skip the current element in the loop and continue with the next iteration of the loop. For example:

#PowerShell ForEach 1..10
$Array = 1..10
Foreach($Val in $Array){
    #Skip 5
    if($val -eq 5){
        Continue
    }
    Write-Host "Value: $val"
}

Output:

Value: 1
Value: 2
Value: 3
Value: 4
Value: 6
Value: 7
Value: 8
Value: 9
Value: 10

In the example above, the foreach loop will iterate through the elements of the $array array. When the loop reaches the element with a value of 5, the “continue” keyword will be encountered, causing the loop to skip the remainder of the current iteration and move on to the next one. 

Continue in ForEach-Object cmdlet

However, When you use break or continue in ForEach-Object cmdlet, the whole loop is terminated instead of skipping the current iteration. You have to use “Return” instead of “Continue”.

#Loop between 1 to 10 numbers
1..10 | ForEach-Object {
    if ($_ -eq 5) {
    return
  }
    Write-host $_
} 

Output:

Value: 1
Value: 2
Value: 3
Value: 4
Value: 6
Value: 7
Value: 8
Value: 9
Value: 10

PowerShell creates the variable $_ to represent the current item in a loop.

Conclusion

Loops are integral to effective scripting. As you can see, the ForEach loop and ForEach-Object cmdlets are very useful for working with collections of objects that allow you to iterate and perform an action on each object. In this article, we’ve explored the ins and outs of PowerShell ForEach, including how it works, best practices for using it, and tips and tricks for writing efficient scripts with this powerful construct.

You now have a solid understanding of when and how to apply ForEach loops and ForEach-Object in your scripts. By using them in your PowerShell scripts, you can perform complex actions on large collections of objects efficiently. Happy looping!

What is the difference between ForEach and for loop in PowerShell?

The main difference between the Foreach and for loop in PowerShell is the way they iterate through a collection. The foreach loop is designed specifically for iterating through arrays or collections, while the for loop is more general and can be used for any type of iteration. Additionally, the syntax and structure of the two loops are different. The foreach loop uses the “foreach” keyword followed by a variable and the collection, while the for loop uses the “for” keyword followed by initialization, condition, and iteration statements.

How do you break out of a ForEach loop in PowerShell?

To break out of a Foreach loop in PowerShell, you can use the “break” keyword. When a condition is met within the loop, you can use “break” to exit the loop and continue with the rest of the script.

What does %{} mean in PowerShell?

The % symbol is the shortcut alias for ForEach-Object cmdlet in PowerShell. E.g.,
1..10 | % { Write-host $_}

How to use the where condition with ForEach in PowerShell?

To use a where condition within a foreach loop in PowerShell, you can pipe the collection to the Where-Object cmdlet and use it to filter the items based on a specific condition. For example, you have an array of numbers, and you want to filter out all the even numbers.

How to use ForEach method with an array in PowerShell?

To use the ForEach method with an array in PowerShell, you can call the method on the array object and pass in a script block that contains the code to be executed for each item in the array. Here is an example:
$Fruits = “apple”, “banana”, “orange”
$Fruits.ForEach({ Write-Host $_ })

Salaudeen Rajack

Salaudeen Rajack - Information Technology Expert with Two-decades of hands-on experience, specializing in SharePoint, PowerShell, Microsoft 365, and related products. He has held various positions including SharePoint Architect, Administrator, Developer and consultant, has helped many organizations to implement and optimize SharePoint solutions. Known for his deep technical expertise, He's passionate about sharing the knowledge and insights to help others, through the real-world articles!

Leave a Reply

Your email address will not be published. Required fields are marked *