Like most procedural programming languages, PowerShell supports a variety of loops. A specialty of Microsoft’s scripting language is that it not only offers a foreach command but also a Foreach-Object cmdlet that allows you to iterate through the elements of an array.

If you have been working with other programming languages, you will quickly feel at home with PowerShell’s various loop types. Their functionality and syntax is based on loops in C and derived languages such as JavaScript. Thus, the loop condition is usually enclosed in parentheses and the loop body in braces. However, the conditional operators that you require for the loop condition need getting used to. Apart from that, PowerShell’s keywords are case-insensitive, so you can use for, For, or FOR.

Loops for different purposes

The different loop types cover all thinkable application scenarios. For instance, PowerShell supports pretest and posttest loops that enable you to evaluate the boolean condition either at the beginning or at the end of the loop body. If you need a loop counter that you want to initialize and increment in the loop condition, you can work with a for loop. However, if you just have to check a certain condition, you can make use of a while loop.

For with integrated loop counter

PowerShell’s for loop doesn’t bring any great surprises and behaves as in other programming languages.

for ($i=1; $i -le 10; $i++) {$i,"`n"}

This simple example initializes the loop counter $i with the value 1. It then increments the counter by one with each iteration until it reaches 10, which is the condition that quits the loop.

While loop

The while loop works just as you might know it from other languages. It is called a pretest loop because the instructions in the loop body are not executed, even once, if the loop condition doesn’t match. In contrast to the for loop, the condition can only contain a boolean expression. If you want to use a loop counter, you have to initialize it before the while statement and increment or decrement it in the loop body. The following snippet demonstrates how you could use while for a simple menu system. With each iteration, the user is asked to press a key to select a menu item. Entering “Q” terminates the loop.

while(($inp = Read-Host -Prompt "Select a command") -ne "Q"){
   L {"File will be deleted"}
   A {"File will be displayed"}
   R {"File will be write protected"}
   Q {"End"}
   default {"Invalid entry"}

while loop example

while loop example

The while loop tests the condition before the first iteration. As you can see in the example, you can also call cmdlets and assign values in the loop condition.

In addition, PowerShell supports the posttest loops do-while and do-until. In both cases, the instructions in the loop body are executed at least once because the condition is at the end of the loop.

From a syntactical point of view, do-while and do-until are identical. The difference is logical in nature. do-while continues to run as long as the condition is true and terminates when the condition is no longer fulfilled; do-until works the other way around: it quits when the condition takes the value TRUE. The general structure looks like this:

   loop body instructions

Basically, do-until and do-while can replace each other if you negate the condition.

Loop control with break and continue

PowerShell offers two additional ways to control loops. The commands break and continue are known from other languages and are rarely required in well-structured scripts. Before you work with these language elements, you should try to avoid them by using another algorithm. Code that uses break and continue is hard to read and can have unwanted side effects.

The break command can be used not only in all loop types but also in switch blocks. The command always has the same effect—that is, the block will be terminated and the control is transferred to the parent block. The break command is comparable to exit for and exit do in VBScript.

Using break in loops quits the iteration, and the following code outside the loop will be executed. For nested loops, this would be the higher order for-, while-, foreach-, or do block. The only situation where the usage of break likely makes sense is within an if statement because otherwise the loop wouldn’t be iterated a second time.

Break with goto

A specialty of PowerShell’s break command is that you can combine it with a label. This works similar to the notorious GoTo in Basic. The only exception is that the targets have to be in the same line with a for-, while-, foreach-, or do- command.

   loop body instructions
   if(condition) {break :DoLoop}
   loop body instructions
:DoLoop do{
   loop body instructions

In this construct, the program would jump to the do loop when the if condition within the while block applies.

Continue command

As with the break command, the continue command terminates the execution of the loop body. In contrast to break, continue doesn’t direct the program flow to the code after the loop; instead, it resumes the execution of the loop in the next iteration. Here, again, use continue sparingly!

Even though PowerShell comes with the complete loop weaponry of compiled languages, you will rarely exploit its entire potential because scripts usually have a relatively simple structure.

Clearly, the most frequent use of loops, especially in interactive mode, is the iteration through the elements of an array because many cmdlets return this data type.

Implicit iteration through array elements

Because of this, Microsoft simplified such operations and allows admins to choose between different methods. Starting with PowerShell 3.0, the simplest and most elegant one is the implicit foreach that, in some cases, allows you to avoid this keyword. The example below demonstrates how you can retrieve a certain property of all array elements without using a loop or Select-Object.

(Get-ADUser -Filter *).Surname

This call of Get-ADUser returns all Active Directory user objects as an array. The above command displays the last name of each element.

Foreach and Foreach-Object

If you want to do more than just display a property of the array elements (for instance, access and process their values), you’ll need an explicit loop. For these cases, PowerShell offers the foreach command and the Foreach-Object cmdlet. This may create confusion because the latter has the predefined alias foreach (in addition to “%”).

The differences between the PowerShell and the VBScript version of foreach are only syntactical in nature. In PowerShell, the keyword is not for each but foreach, and, instead of closing the loop body with a next command, you use braces.

$user = Get-ADUser -Filter *
foreach($u in $user) {

These lines fulfill the same purpose as the previous example with the implicit loop. However, the result of Get-ADUser is assigned to the variable $user. Afterward, you need an additional variable ($u), which always contains the current element of the array.

If you want to solve the above problem with Foreach-Object, you have to pipe the output of Get-ADUser to Foreach-Object and use the automatic variable $_ to refer to the current element, like this:

Get-ADUser -Filter *| %{ if($_.surname) {(Get-Culture).TextInfo.ToTitleCase( $_.surname)}}

The command in this example doesn’t just retrieve the last names of the AD users but also uses the ToTitleCase method to convert the initial letters into capital letters if the property surname is unequal to NULL. Notice that I used the alias “%” for Foreach-Object. The parentheses around the Get-Culture cmdlet (which gets information such as current language settings) ensure that the TextInfo property is applied to the result (an object) returned by the cmdlet.

Since commands with the Foreach-Object and the implicit foreach are shorter and require less typing (not just because of the alias “%”), no reason appears to exist to work with the foreach command itself. However, when you have a large number of loop passes with relatively complex calculations in the loop body, the conventional foreach loop is significantly faster.

  1. Avatar
    Emmanuel 8 years ago

    Thank you for the info.

    A small correction is needed in this text:
    “do-while continues to run as long as the condition is true and terminates when the condition is no longer fulfilled; do-while works the other way around:”

    The second “do-while” should be “do-until”

  2. Avatar
    Wolfgang Sommergut 8 years ago

    @Emmanuel: You are right. Thank you!

  3. Avatar

    I corrected the sentence now. Thanks!

  4. Avatar
    robk 8 years ago

    can you have multiple statements inside while?
    While ($a=1 -or $a=2 -or $a=3)?

    • Avatar
      Aaron Gochee 4 years ago

      Yes, you can:

      do {$a = $a + 1} while ($a -eq 2 -or $a -eq 3 -or $a -eq 4)

      You will end up with 5.

  5. Avatar
    Anonymous Freetard 6 years ago

    “The commands break and continue are known from other languages and are rarely required in well-structured scripts.”
    Now that is a preposterous statement. Untold numbers of useful scripts and programs follow an “infinite loop” paradigm where the basic structure should be while(true) {do …} and the only way out is a “break” within the infinite loop. Any cleanup operations should be below the loop and not within the loop for code clarity so that is why a break is required and not an explicit exit. An Operating System itself is an example of an infinite loop paradigm.

  6. Avatar
    Thomas Visel 6 years ago

    So agreed with Freetard.  The original article contained multiple instances of personal opinion.  They clashed with those of many colleagues… and my own!  The infinite loop paradigm Freetard notes is a powerful one-exit-target structure, crystal clear in its intent and use.

  7. Avatar
    Javed Bukhari 7 months ago

    looking for a way to break the loop with “Return Key” Space or any other key.

Leave a reply

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


© 4sysops 2006 - 2023


Please ask IT administration questions in the forums. Any other messages are welcome.


Log in with your credentials


Forgot your details?

Create Account