Introduction
Continuing my series on PowerShell basics, in this installment we’ll talk bout looping in PowerShell. Looping is a mechanism for repeating a set of instructions multiple times, ending once a condition is met. Looping is also known as iterating, as in “iterating over an array”.
Loops continue until one of two things happen. In one type of loop, the loop continues until a certain condition is true. In the second type, the loop will iterate over a collection (also called an array) of objects until the entire collection has been gone through.
For all of the examples, we’ll display the code, then under it the result of our code. In this article I’ll be using PowerShell Core, 7.1.3, and VSCode. The examples should work in PowerShell 5.1 in the PowerShell IDE, although they’ve not been tested there.
To run a snippet of code highlight the lines you want to execute, then in VSCode press F8 or in the IDE F5. You can display the contents of an array variable (or any variable) by highlighting it and using F8/F5.
While
The while
loop continues as long as a condition is true. Let’s take a look at an example.
$i = 1
while ($i -le 5)
{
"`$i = $i"
$i = $i + 1
}
Result:
$i = 1
$i = 2
$i = 3
$i = 4
$i = 5
In a while loop, you start with the keyword while
, then pass in a condition. In this case, it will keep looping as long as $i
is less than or equal to 5. Once $i
is greater than 5, it will exit the loop.
Inside the loop we print out the value of $i
, then increment the value of $i
by 1.
So what happens if $i
had been set to the value of 6, as in:
$i = 6
while ($i -le 5)
{
"`$i = $i"
$i = $i + 1
}
Result:
(Nothing is displayed)
In this case, the while
keyword checked the value at the start of the loop. Since $i
was already greater than 5, the loop never executed. So when using a while
loop, be sure to understand there may be conditions under which the while
loop will never execute.
Fun with Unary Operators
Before we see the next type of loop, I just want to mention unary operators. In the previous section you saw $i = $i + 1
. Obviously this increased the value of $i
by one.
There is an alternative syntax, the unary operator. With the unary operator, you use ++
either before or after the variable, as in $i++
or ++$i
, to increment it. You can also use --
to decrement the value by one.
So what is the difference between $i++
and ++$i
? It has to do with when the value is incremented. Let’s look at this example.
$i = 1
"`$i is $(($i++))"
"`$i is now $i"
Result:
$i is 1
$i is now 2
In this case we start by assigning the value of 1 to $i
. We then have a string, "`$i is $(($i++))"
. In the results, it prints out $i = 1
.
In this case, when ++
follows a variable the value is returned, then the variable is incremented. As PowerShell evaluates the string, it replaces $i
with the value of 1, prints out $i is 1
, and then it increments the value $i
to 2.
In the final statement it displays the result of the incremented value.
What if the ++
occurs before the variable?
$i = 1
"`$i is $((++$i))"
"`$i is now $i"
Result:
$i is 2
$i is now 2
With ++
before the variable, the value in $i
is incremented first, then the result is returned. So when PowerShell evaluated $((++$i))
it incremented the value of $i
by one, now making it 2, then returned it to the string.
We took this detour into unary operators because it’s very common to use an expression like $i++
within a loop to increment the value, as you’ll see in the remaining examples.
Do While
With the while
loop, you saw that it was possible that it might not execute, if the while condition was already true. What if, though, you always wanted the loop to execute at least once?
That’s where do while
comes into play.
$i = 1
do
{
"`$i = $i"
$i++
} while($i -le 5)
Result:
$i = 1
$i = 2
$i = 3
$i = 4
$i = 5
This is a similar result to what we experienced with while. But, what if $i was already greater than 5, as in the next example.
$i = 33
do
{
"`$i = $i"
$i++
} while($i -le 5)
Result:
$i = 33
Because the while check didn’t occur until the very end of the loop, we are guaranteed that it will execute the code within our do
‘s script block at least once, and hence it printed $i = 33
.
Do Until
As an alternative to do while
, there is do until
. With do while
it continues to loop as long as a condition is true.
Contrast this with do until, which keeps looping as long as the condition is not true.
$i = 1
do
{
"`$i = $i"
$i++
} until($i -gt 5)
Result:
$i = 1
$i = 2
$i = 3
$i = 4
$i = 5
In this case, once $i
is greater than 5, the loop exits. There’s not much difference between do while
and do until
. It’s mostly a matter of how you like to think about your code.
Does it make more sense, or will it increase code readability, to write your code so that it keeps looping while a condition is true, or until it becomes true.
For
Another loop you can have fun with is the for
loop. The for
loop is ideal when you want to iterate over code a set number of times.
for ($f = 0; $f -le 5; $f++)
{
"`$f = $f"
}
Result:
$f = 0
$f = 1
$f = 2
$f = 3
$f = 4
$f = 5
After the for
, you pass in three expressions, separated by semicolons ;
. The first expression you pass in sets the starting value for the variable we’ll increment each time through the loop. In this case, $f = 0
will (obviously) set the variable $f to 0
(zero). $f
will be come the value we’ll increment each time through the loop.
The second expression is just like what you would use on a while
/do while
loop. As long as this condition is true it will keep looping. In this case, the expression $f -le 5
will keep looping as long as $f
is less than or equal to 5.
Finally we have an expression that we want to execute at the end of the loop. Here, we’ll use a unary operator to increase the value of $f
by 1.
So let’s express this in human terms.
- Set the value of
$f
to zero. - Is
$f
less than or equal to 5? If yes, go into the script block. If no, exit the loop. - Now execute all the code in the script block.
- At the end of the script block, add 1 to
$f
. - Go back to step 2.
As you can see, the for is very similar to a while loop. If $f is already over 5 (in this example) the loop will not execute at all. Like while, it will keep looping as long as our condition is true.
The for
is a little more compact than a while
loop as you can include the increment option in the for command rather than having to include it in the script block.
ForEach
By far, the foreach loop is the one I use more than any other. The foreach loop allows you to iterate over an array (or a collection of objects, which is really just an array).
With for each you create a place holder variable then pass in the name of the array. Here, take a look at this example.
$array = 11,12,13,14,15 # Simple Array
foreach ($item in $array)
{
"`$item = $item"
}
Result:
$item = 11
$item = 12
$item = 13
$item = 14
$item = 15
We create an array of numbers and assign them to the variable $array.
Then in the foreach
loop, we go over the array item by item. As each item is read from the array it is copied into the first variable in the foreach
clause, in this case $item
.
It then simply executes the code in the script block, when done it grabs the next item from $array
, copies it into $item
, and repeats the script block.
In this case we looped over a simple array of integers, but foreach
can also loop over something more complex like a collection of objects. In this next example we’ll use the Get-ChildItem
cmdlet to get a list of files from the current directory. As it goes over each one it will copy that file object into our $file
variable, then we can use it in the script block.
foreach ($file in Get-ChildItem)
{
$file.Name
}
Result:
01 - Cmdlets.ps1
02 - Providers.ps1
03 - Variables.ps1
04 - Strings.ps1
05 - Arrays and Hashtables.ps1
06 - Logic Branching and Looping.ps1
07 - Functions.ps1
08 - Classes.ps1
09 - Examples.ps1
ReadMe.md
The script block is very simple, it just references the Name property of the $file
object and displays it on the screen.
Now many people might have coded this as:
$myFiles = Get-ChildItem
foreach($file in $myFiles)
...
Which is perfectly valid code. I just wanted to show that if the only reason you needed the $myFiles
variable was to hold information to iterate over, and you weren’t going to reference it again in your code, you could skip it and just use the cmdlet right in the foreach loop.
Code Formatting
In my previous post I dove into the Code Formatting around PowerShell. In all my examples, I used a space between the loop keyword and parenthesis that enclosed the condition. In addition I put the opening squiggly brace on the next line.
Neither is necessary, this is perfect valid code:]
$i = 1
while($i=1){
# Do some stuff
}
Conclusion
In this post, we looked at several ways to iterate over your code. This included several variations on while, as well as for and the useful foreach. Now you have several tools at your disposal when you need to run the same piece of code multiple times.
The demos in this course came from my Pluralsight course PowerShell 7 Quick Start for Developers on Linux, macOS and Windows, one of many PowerShell courses I have on Pluralsight. All of my courses are linked on my About Me page.
If you don’t have a Pluralsight subscription, just go to my list of courses on Pluralsight. At the top is a Try For Free button you can use to get a free 10 day subscription to Pluralsight, with which you can watch my courses, or any other course on the site.