Welcome PowerShell User! This recipe is just one of the hundreds of useful resources contained in the PowerShell Cookbook.

If you own the book already, login here to get free, online, searchable access to the entire book's content.

If not, the Windows PowerShell Cookbook is available at Amazon, or any of your other favourite book retailers. If you want to see what the PowerShell Cookbook has to offer, enjoy this free 90 page e-book sample: "The Windows PowerShell Interactive Shell".

4.4 Repeat Operations with Loops

Problem

You want to execute the same block of code more than once.

Solution

Use one of PowerShell’s looping statements (for, foreach, while, and do) or PowerShell’s ForEach-Object cmdlet to run a command or script block more than once. For a detailed description of these looping statements, see “Looping Statements”. For example:

for loop
for($counter = 1; $counter -le 10; $counter++)
{
  "Loop number $counter"
}
foreach loop
foreach($file in dir)
{
  "File length: " + $file.Length
}
ForEach-Object cmdlet
Get-ChildItem | ForEach-Object { "File length: " + $_.Length }
while loop
$response = ""
while($response -ne "QUIT")
{
  $response = Read-Host "Type something"
}
do..while loop
$response = ""
do
{
  $response = Read-Host "Type something"
} while($response -ne "QUIT")
do..until loop
$response = ""
do
{
  $response = Read-Host "Type something"
} until($response -eq "QUIT")

Discussion

Although any of the looping statements can be written to be functionally equivalent to any of the others, each lends itself to certain problems.

You usually use a for loop when you need to perform an operation an exact number of times. Because using it this way is so common, it is often called a counted for loop.

You usually use a foreach loop when you have a collection of objects and want to visit each item in that collection. If you do not yet have that entire collection in memory (as in the dir collection from the foreach example shown earlier), the ForEach-Object cmdlet is usually a more efficient alternative.

Unlike the foreach loop, the ForEach-Object cmdlet lets you process each element in the collection as PowerShell generates it. This is an important distinction; asking PowerShell to collect the entire output of a large command (such as Get-Content hugefile.txt) in a foreach loop can easily drag down your system.

Like pipeline-oriented functions, the ForEach-Object cmdlet lets you define commands to execute before the looping begins, during the looping, and after the looping completes:

PS > "a","b","c" | ForEach-Object `
    -Begin { "Starting"; $counter = 0 } `
    -Process { "Processing $_"; $counter++ } `
    -End { "Finishing: $counter" }

Starting
Processing a
Processing b
Processing c
Finishing: 3
Tip

To invoke multiple operations in your loop at the same time, use the -parallel switch of ForEach-Object. For more information, see Recipe 4.5.


The while and do..while loops are similar, in that they continue to execute the loop as long as its condition evaluates to true. A while loop checks for this before running your script block, whereas a do..while loop checks the condition after running your script block. A do..until loop is exactly like a do..while loop, except that it exits when its condition returns $true, rather than when its condition returns $false.

For a detailed description of these looping statements, see “Looping Statements” or type Get-Help about_For, Get-Help about_Foreach, Get-Help about_While, or Get-Help about_Do.

See Also

Recipe 4.5, “Process Time-Consuming Action in Parallel”

“Looping Statements”