---
title: "PowerShell Loops: A Practical Guide to foreach, for, and do Loops"
description: "Learn how to use PowerShell loops effectively in this comprehensive guide covering foreach, for, and do loops with practical real-world examples."
canonical: "https://adamtheautomator.com/powershell-loops-practical-guide/"
---

# PowerShell Loops: A Practical Guide to foreach, for, and do Loops

> Learn how to use PowerShell loops effectively in this comprehensive guide covering foreach, for, and do loops with practical real-world examples.

Source: https://adamtheautomator.com/powershell-loops-practical-guide/

---

ATA Learning

Tap to hide

[

ATA Learning

](/)

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Search for:  

*   [](https://twitter.com/adbertram)
*   [](https://github.com/Adam-the-Automator)
*   [](https://www.linkedin.com/company/adam-the-automator-llc)
*   [](/feed/)

![PowerShell Loops: A Practical Guide to foreach, for, and do Loops](https://adamtheautomator.com/wp-content/uploads/2024/12/featured-image-2.webp)

# PowerShell Loops: A Practical Guide to foreach, for, and do Loops

[![](https://secure.gravatar.com/avatar/d0b9d42e21e5622713f8b693aa5c0f9244d5f7dd200ed29b8398f52dee5de337?s=192&d=mm&r=g)Adam Bertram](https://adamtheautomator.com/author/adam-bertram/)20 December 20246 min. read

Categories: [IT Ops](/category/it-ops/)

Tags:[PowerShell](/tag/powershell/)

Table of Contents

*   [Mastering foreach Loops: Iterating with Ease](#mastering-foreach-loops-iterating-with-ease)
*   [Unlocking the Power of for Loops: Flexibility and Control](#unlocking-the-power-of-for-loops-flexibility-and-control)
*   [Exploring do Loops: Ensuring Actions Before Conditions](#exploring-do-loops-ensuring-actions-before-conditions)
*   [Conclusion](#conclusion)

One of PowerShell’s key features is its ability to loop through data collections, enabling you to execute a code block repeatedly.

In this tutorial, we will explore three fundamental loop structures in PowerShell: `foreach`, `for`, and `do` loops.

By the end of this tutorial, you will have a solid understanding of how to use these loops to handle repetitive tasks and process collections of data more effectively.

## Mastering `foreach` Loops: Iterating with Ease

When you need to execute a code block for every item, the `foreach` loop makes repetitive tasks simple and efficient. This loop is a more complex but ever-so-common structure that works wonders whether you’re working with an array of server names or processing any other collection.

Every `foreach` performs a common task; it allows you to run some code _for each_ element in a collection. It performs ‘iteration’ to ‘iterate over’ each element in that collection, enabling you to address each element individually.

This first example has an array of strings representing server names. The goal is to simply read each string in that array.

```
$servers = @('localhost','SRV2','SRV3','SRV4')
```

Create a `foreach` loop with a variable called `$server` that represents each element in that array as it’s processing.

```powershell
foreach ($server in $servers) {
    Write-Host "I'm processing server $server right now..."
}
```

You can see that PowerShell ran the `Write-Host` command and read each item in the array. PowerShell knew how many times to run because of how many items were in the array.

![Iterating over each element in the array and running some code ](https://adamtheautomator.com/wp-content/uploads/2024/07/Untitled.png)

If you ever have a large array, you can always use the `Count()` method to see how many times the loop would run.

```
$servers.Count
```

![Checking loop iteration count](https://adamtheautomator.com/wp-content/uploads/2024/12/loop-iteration-count.png)

You can also use the `ForEach-Object` cmdlet, which is handy when you’d like to use the pipeline iterating over each item in an array. Typically, you’ll see the `ForEach-Object` cmdlet used with the pipeline.

```powershell
ForEach-Object -InputObject $servers -Process {
    Write-Host "I'm processing server $server right now..."
}
```

![Specifying the collection of items to be processed](https://adamtheautomator.com/wp-content/uploads/2024/12/for-each-object.png)

Since the `ForEach-Object` cmdlet’s `InputObject` parameter supports pipeline input, you can pipe the collection directly to it. Exclude the `Process` parameter name and include the scriptblock immediately after the `ForEach-Object` call.

This method works great when processing small collections but can be slower when working with extensive collections.

```powershell
$servers | ForEach-Object {
    Write-Host "I'm processing server $_ right now..."
}
```

![Piping the collection directly to \`ForEach-Object\` for small collections](https://adamtheautomator.com/wp-content/uploads/2024/12/pipe-foreach.png)

And finally, we have the `foreach()` method. As with earlier options, you can use this method on arrays, not a statement or command. It’s the fastest `foreach` loop, run by typical dot notation executing a method on an object with a scriptblock inside.

```powershell
$servers.foreach({Write-Host "I'm processing server $_ right now..."})
```

Every `foreach` loop is generally the same when processing small collections. You can typically go with a `foreach` statement. Why? Because you can define a descriptive variable instead of using the pipeline variable (the dollar underscore), which isn’t as intuitive.

![Choosing a descriptive foreach loop variable srcset=](https://adamtheautomator.com/wp-content/uploads/2024/12/var.foreach.png)

## Unlocking the Power of `for` Loops: Flexibility and Control

Next up, we have `for` loops. `For` loops are loops that aren’t quite as smart as `foreach` loops. `For` loops have no idea how many elements are in a collection. `For` loops start at a number, increment that number each time, and stop when a condition is true.

The `for` loop has four different elements to it:

| Element | Function |
| --- | --- |
| Iterator variable (e.g., `$i`) | Typically defined as `$i`‘s starting point, which is at `0` here. |
| Condition (`$true` or `$false`) | The condition that must be met for the loop to continue. In this case, `$true`. |
| Action (e.g., `$i++`) | The action to perform for each iteration. You’ll typically see this to be `$i++` which increments the variable by `1` for each iteration. |
| Scriptblock `{}` | The scriptblock, enclosed in `{}` contains the code to run for each iteration. |

In this example, this `for` loop:

*   Sets the iterator variable to `0`.
*   Runs the code in the scriptblock, which is a `Write-Host` reference.
*   Checks to see if the iterator variable is less than `10`, which it is.
*   Increments by `1` (`$i++`), setting the value to `1` since the iterator variable is less than `10`.
*   Reruns the code and repeats that pattern.

```powershell
## The for Loop (Allows you to reference element indexes dynamically)
for ($i = 0; $i -lt 10; $i++) {
    Write-Host "I'm on iteration number $i now."
}
```

To apply `for` loops to arrays, you can use the fact that arrays have an index starting at `0` and incrementing by `1` to mimic a `foreach` loop.

```
## Change the value of array items
for ($i = 0; $i -lt $servers.Length; $i++) {
    $servers[$i] = "new $($servers[$i])"
}
$servers
```

Another handy use of `for` loops is the ability to reference past and future elements while processing a current element.

For instance, you may need to reference the server name you just processed. You can’t do so in a `foreach` loop.

But in a `for` loop, you add or subtract from the iterator variable and use it as an array index to reference the server name you need.

```powershell
## Reference elements before or after based on the current item
for ($i = 1; $i -lt $servers.Length; $i++) {
    Write-Host $servers[$i] "comes after" $servers[$i-1]
}
```

Let’s finish off `for` loops with a real example based on the scenario we’ve been working with but changed up slightly.

You may need to read the contents of some application configuration files from multiple servers. The problem is that the file name isn’t the same on each server but follows a pattern. There’s a number in the file name, as you can see below (e.g., `App_configuration1.txt`).

We can’t simply use a `foreach` loop here because the file name differs every time. But since the file has an incrementing number, a `for` loop will work.

Create a `for` loop that:

*   Runs for as many elements as the `$servers` array has. You must define the iterator variable as less than the count of all elements in the `$servers` array.
*   References each `$servers` array index inside the script block that starts at `0` and increments the value by `1` to create the number in the configuration file.

```powershell
## But what if the problem is a little more complex? A number in the file name
$servers = @('localhost','SRV2','SRV3','SRV4')
Get-Content -Path "\\$($servers[0])\c$\App_configuration1.txt"
Get-Content -Path "\\$($servers[1])\c$\App_configuration2.txt"
Get-Content -Path "\\$($servers[2])\c$\App_configuration3.txt"
Get-Content -Path "\\$($servers[3])\c$\App_configuration4.txt"

for ($i = 0; $i -lt $servers.Count; $i++) {
    Write-Host "Processing servers array index number $i which is server $($servers[$i])..."
    Write-Host "The next servers array index after this one is $($i + 1)."
    Write-Host "Looking for file name App_configuration$($i+1).txt..."
    Get-Content -Path "\\$($servers[$i])\c$\App_configuration$($i+1).txt"
}
```

You can see that the `for` loop processed each `Get-Content` command to read the appropriate file on the appropriate server.

## Exploring `do` Loops: Ensuring Actions Before Conditions

Let’s finish off loops with a few useful ones that may not be as common as `foreach` and `for`, but when you need them, they come in clutch.

First up is the `while` loop. The `while` loop is useful when running a code while something else is in a particular state or meets a specific condition (e.g., a counter).

This `while` loop only runs while the `$counter` variable is less than `10`.

```
## The while Loop (Do something while a specific state for something else)

$counter = 0
while ($counter -lt 10) {
    $counter
    $counter++
}
```

To prevent an infinite loop that never stops, add a scriptblock code incrementing the counter by `1` for each iteration. The loop returns `0` through `9`, which is the value of `$counter` at the time of each iteration.

Now, let’s cover a real example.

For this `while` loop, it’s pinging a machine constantly only while it returns a `$true` value. So you don’t DOS the machine; it’s pausing for one second between attempts.

You can create some advanced wait functions with `while` loops like this.

```
## Ping SOMESERVER every second only while Test-Connection returns true
while (Test-Connection -ComputerName 'SOMESERVER' -Quiet -Count 1) {
    Start-Sleep -Seconds 1
}
Write-Host 'SOMESERVER is now offline.'
```

Next up is the `do/while` loop. This loop is similar to the `while` loop, but unlike the `while` loop, it always performs an action (the `do` part) and enters into that `while` loop.

Below is a nonsense way to use a `do/while` loop.

```powershell
## The do/while loop (Do something THEN CONTINUE doing something until a condition is met)
do {
    $choice = Read-Host -Prompt 'What is the best programming language?'
} while ($choice -ne 'PowerShell')
```

Notice that it won’t exit the loop before I give the “correct” answer. The loop continues to run the `Read-Host` command continuously when the answer isn’t what it wants it to be.

And finally, we have the `do/until` loop.

Similar to the `do/while` loop, the `do/until` loop does something and then stops when a condition is met. This loop defines the stop condition and not the continuation condition.

```powershell
## The do/until loop (Do something THEN STOP when a condition is met)
do {
    $choice = Read-Host -Prompt 'What is the best programming language?'
} until ($choice -eq 'PowerShell')
Write-Host -Object 'Correct!'
```

You can replicate the same scenario by flipping the not equal operator to equal in this loop.

Note that the `do/until` loop allows you to run some code after it meets the condition it was looking for—a feat impossible with the `do/while` loop.

## Conclusion

Loops are essential in scripting for automation, and mastering the `foreach`, `for`, and `do` loops in PowerShell opens up a world of possibilities for handling complex tasks.

Whether you’re iterating through a list of servers, performing checks on multiple files, or running actions until a specific condition is met, these loops provide flexibility and control. They allow you to streamline your processes effectively.

Following these examples, you can now apply these loops to your scripts, making your automation tasks efficient and scalable.

Share this article

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fadamtheautomator.com%2Fpowershell-loops-practical-guide%2F&text=PowerShell%20Loops%3A%20A%20Practical%20Guide%20to%20foreach%2C%20for%2C%20and%20do%20Loops)[Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fadamtheautomator.com%2Fpowershell-loops-practical-guide%2F)[Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fadamtheautomator.com%2Fpowershell-loops-practical-guide%2F)

## Related Posts

![](https://adamtheautomator.com/wp-content/uploads/2026/06/26995-troubleshoot-dns-issues-powershell-codex.webp)

### [Troubleshoot DNS Issues with PowerShell](/troubleshoot-dns-issues-powershell/)

Troubleshoot DNS issues with PowerShell by testing name resolution, DNS client settings, cache entries, and network connectivity in a repeatable workflow.

![](https://adamtheautomator.com/wp-content/uploads/2025/10/image_2025-10-24_095322075.png)

### [Migrating from PowerShell 6 to 7.5: Breaking Changes/New Features](/migrating-powershell-6-to-7-5/)

Migrate from PowerShell Core 6 to 7.5: breaking changes, features, and testing tips.

![](https://adamtheautomator.com/wp-content/uploads/2025/06/featured-image-6.png)

### [How to Add Timeouts to Pester Tests with PowerShell Runspaces](/pester-test-timeout-runspaces/)

Prevent Pester tests from hanging indefinitely using PowerShell runspaces. Learn to handle variable scoping, module loading, TestDrive access, and stream capture challenges with timeout protection.

## Categories

*   [IT Ops](/category/it-ops/)
*   [Cloud](/category/cloud/)
*   [DevOps](/category/devops/)
*   [Home Ops](/category/home-ops/)
*   [Information Security](/category/infosec/)
*   [Software Development](/category/software-development/)

## Site

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Copyright 2026© ATA Learning | [Privacy Policy](/privacy/)
