A PowerShell for loop runs a block of code a set number of times. You give it a starting value, a condition and a step, and PowerShell repeats the block while the condition is true:
for (<init>; <condition>; <repeat>) {
<statement list>
}
Here’s the simplest real example, counting from 1 to 5:
for ($i = 1; $i -le 5; $i++) {
"Pass number $i"
}
Output:
Pass number 1
Pass number 2
Pass number 3
Pass number 4
Pass number 5
Below, you’ll see how each part works, how to loop from 1 to 10, step by 2, count backwards and walk an array by index. I’ll also cover break, continue, the mistakes I see most, and when foreach is the better choice.
I ran every example in PowerShell 7.6 and Windows PowerShell 5.1. The for loop behaves the same in both.
How the three parts of a for loop work
| Part | Example | When it runs |
|---|---|---|
| Init | $i = 1 | Once, before the first pass |
| Condition | $i -le 5 | Before every pass. The loop stops as soon as it’s $false |
| Repeat | $i++ | After every pass, before the condition is checked again |
Because the condition is checked first, the body may never run. for ($i = 10; $i -le 5; $i++) does nothing at all.
Microsoft’s about_For documentation describes the full syntax.
PowerShell for loop from 1 to 10
To loop from 1 to 10, start at 1 and keep going while the counter is less than or equal to 10:
for ($i = 1; $i -le 10; $i++) {
Write-Output $i
}
Output:
1
2
3
4
5
6
7
8
9
10
When you just need the numbers and don’t care about the counter logic, the range operator 1..10 with foreach is shorter. This one builds server names with a two-digit number:
foreach ($i in 1..10) {
"Server{0:D2}" -f $i
}
Output:
Server01
Server02
Server03
Server04
Server05
Server06
Server07
Server08
Server09
Server10
Count by 2 or count backwards
The repeat part doesn’t have to be $i++. Use $i += 2 to step by two, or $i-- with -ge to count down:
# count by 2
for ($i = 0; $i -le 10; $i += 2) { $i }
'---'
# count down from 5 to 1
for ($i = 5; $i -ge 1; $i--) { $i }
Output:
0
2
4
6
8
10
---
5
4
3
2
1

Loop through an array by index
This is where the for loop really earns its place. You get the position of each item, not just the item:
$states = 'California', 'Texas', 'Florida', 'New York', 'Ohio'
for ($i = 0; $i -lt $states.Count; $i++) {
"{0}. {1}" -f ($i + 1), $states[$i]
}
Output:
1. California
2. Texas
3. Florida
4. New York
5. Ohio

Arrays start at 0, so the condition is $i -lt $states.Count, not -le. I add 1 only when I print the number for humans.
Change array items in place
A foreach loop gives you a copy of each value, so assigning to it doesn’t change the array. With the index, you can update the array directly:
$prices = 19.99, 5.25, 42.00
for ($i = 0; $i -lt $prices.Count; $i++) {
$prices[$i] = [math]::Round($prices[$i] * 1.08, 2) # add 8% sales tax
}
$prices
Output:
21.59
5.67
45.36
Loop through an array in reverse
Start at the last index and count down to 0. It’s handy for undo steps or when you remove items while looping:
$steps = 'Download', 'Extract', 'Install', 'Configure'
for ($i = $steps.Count - 1; $i -ge 0; $i--) {
"Undo: $($steps[$i])"
}
Output:
Undo: Configure
Undo: Install
Undo: Extract
Undo: Download
Use two counters in one for loop
You can move two variables at once. Wrap each assignment in parentheses and separate them with a comma, then do the same in the repeat part:
for (($i = 0), ($j = 10); $i -lt 3; $i++, $j--) {
"i = $i, j = $j"
}
Output:
i = 0, j = 10
i = 1, j = 9
i = 2, j = 8
Break and continue in a for loop
continue skips the rest of the current pass. break leaves the loop completely:
for ($i = 1; $i -le 10; $i++) {
if ($i % 2 -eq 0) { continue } # skip even numbers
if ($i -gt 7) { break } # stop after 7
$i
}
Output:
1
3
5
7
You can also leave out all three parts to get an endless loop. Just make sure something inside calls break:
$attempt = 0
for (;;) {
$attempt++
"Attempt $attempt"
if ($attempt -eq 3) { "Done"; break }
}
Output:
Attempt 1
Attempt 2
Attempt 3
Done
For more ways to stop a loop early, see how to break out of a foreach loop in PowerShell.
Nested for loops
Put one for loop inside another to work through rows and columns. This prints a small multiplication table:
for ($row = 1; $row -le 3; $row++) {
$line = for ($col = 1; $col -le 5; $col++) { '{0,4}' -f ($row * $col) }
-join $line
}
Output:
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
Common for loop mistakes in PowerShell
Using < instead of -lt
PowerShell uses -lt, -le, -gt and -ge for comparisons. The < sign is reserved, so this won’t even start:
for ($i = 0; $i < 3; $i++) { $i }
Output:
ParserError: C:\psfaqs\lt.ps1:1
Line |
1 | for ($i = 0; $i < 3; $i++) { $i }
| ~
| The '<' operator is reserved for future use.
Going one step past the end of the array
This one is sneakier, because PowerShell doesn’t throw an error. Reading past the end of an array just returns $null:
$letters = 'a', 'b', 'c'
for ($i = 0; $i -le $letters.Count; $i++) {
"[$i] = '$($letters[$i])'"
}
Output:
[0] = 'a'
[1] = 'b'
[2] = 'c'
[3] = ''
That extra empty pass can write a blank line to a report or call a cmdlet with an empty value. Use -lt $array.Count for arrays.
for vs. foreach vs. ForEach-Object: which is faster?
I timed 100,000 iterations of the same simple calculation on my PC. Your numbers will differ, but the order is the same every time I run it:
$n = 100000
"for: {0,5:N0} ms" -f (Measure-Command { for ($i = 0; $i -lt $n; $i++) { $null = $i * 2 } }).TotalMilliseconds
"foreach: {0,5:N0} ms" -f (Measure-Command { foreach ($i in 1..$n) { $null = $i * 2 } }).TotalMilliseconds
"ForEach-Object: {0,5:N0} ms" -f (Measure-Command { 1..$n | ForEach-Object { $null = $_ * 2 } }).TotalMilliseconds
Output:
for: 115 ms
foreach: 38 ms
ForEach-Object: 433 ms

In the run above, foreach finished in about 38 ms, for in 115 ms, and ForEach-Object took 433 ms because every item goes through the pipeline.
My rule of thumb: use foreach to process every item, for when you need the index or a custom step, and ForEach-Object when you’re already in a pipeline.
Read more in the PowerShell foreach loop and ForEach-Object in PowerShell.
Frequently Asked Questions
What is the syntax of a for loop in PowerShell?
for (<init>; <condition>; <repeat>) { <statements> }, for example for ($i = 1; $i -le 10; $i++) { $i }.
How do I loop from 1 to 10 in PowerShell?
Use for ($i = 1; $i -le 10; $i++) { $i }, or the shorter foreach ($i in 1..10) { $i }.
How do I get the index in a PowerShell loop?
Use a for loop and read the item with $array[$i]. If you prefer foreach, keep your own counter variable and increment it inside the loop.
How do I exit a for loop early in PowerShell?
Call break to leave the loop, or continue to skip to the next pass.
Why doesn’t my for loop run at all?
The condition is checked before the first pass. If it’s already false, for example $i = 10; $i -le 5, the body never runs.
Keep going with these PowerShell loop tutorials:
- PowerShell foreach loop
- While loop in PowerShell
- PowerShell ForEach-Object
- Break out of a foreach loop in PowerShell
Bijay Kumar is an esteemed author and the mind behind PowerShellFAQs.com, where he shares his extensive knowledge and expertise in PowerShell, with a particular focus on SharePoint projects. Recognized for his contributions to the tech community, Bijay has been honored with the prestigious Microsoft MVP award. With over 15 years of experience in the software industry, he has a rich professional background, having worked with industry giants such as HP and TCS. His insights and guidance have made him a respected figure in the world of software development and administration. Read more.