PowerShell While, Do-While and Do-Until Loops

A while loop in PowerShell repeats a block of code as long as its condition is true. It checks the condition before each pass, so the block may never run at all:

$attempt = 1

while ($attempt -le 3) {
    "Checking the backup server, attempt $attempt"
    $attempt++
}
"Done after $($attempt - 1) attempts"

Output:

Checking the backup server, attempt 1
Checking the backup server, attempt 2
Checking the backup server, attempt 3
Done after 3 attempts
PowerShell while loop example with a counter
A while loop that runs three times (PowerShell 7)

Don’t forget the line that changes the counter. Without $attempt++, the condition stays true and the loop never ends.

I ran every example in PowerShell 7.6 and Windows PowerShell 5.1, and the results were the same.

while vs do-while vs do-until

LoopChecks the conditionKeeps running whileRuns at least once
while (...) { }Before each passThe condition is trueNo
do { } while (...)After each passThe condition is trueYes
do { } until (...)After each passThe condition is falseYes

Here all three start with a condition that’s already met. Only the two do loops run their block:

$count = 10

while ($count -lt 5) {
    "while ran with count $count"
}

do {
    "do-while ran with count $count"
} while ($count -lt 5)

do {
    "do-until ran with count $count"
} until ($count -ge 5)

Output:

do-while ran with count 10
do-until ran with count 10
PowerShell while vs do-while vs do-until loops when the condition starts false
The do loops run once, the while loop doesn’t (Windows PowerShell 5.1)

Use a do loop when the block has to run first, like asking for input before you can check it.

When you know exactly how many times to repeat, a for loop is often clearer.

PowerShell do-while loop

A do-while loop runs the block, then repeats it while the condition is true:

$page = 0

do {
    $page++
    "Downloading page $page of 3"
} while ($page -lt 3)

Output:

Downloading page 1 of 3
Downloading page 2 of 3
Downloading page 3 of 3

Microsoft covers both do forms in about_Do.

PowerShell do-until loop

A do-until loop is the reverse. It repeats until the condition becomes true, which often reads more naturally:

$balance = 1000
$month = 0

do {
    $month++
    $balance -= 250
    "Month ${month}: `$$balance left"
} until ($balance -le 0)

Output:

Month 1: $750 left
Month 2: $500 left
Month 3: $250 left
Month 4: $0 left

${month} keeps the colon after the variable name from being read as part of it.

Use multiple conditions in a loop

Combine conditions with -and and -or. This loop stops when it connects or after five attempts, whichever comes first:

$attempt = 0
$connected = $false

while (-not $connected -and $attempt -lt 5) {
    $attempt++
    $connected = ($attempt -eq 3)
    "Attempt ${attempt}: connected = $connected"
}

Output:

Attempt 1: connected = False
Attempt 2: connected = False
Attempt 3: connected = True

A retry limit like this keeps a loop from running forever when something never succeeds. about_While has the full syntax.

Why does my Read-Host loop accept the wrong numbers?

Read-Host always returns text. When text is on the left of -le or -gt, PowerShell compares it as text, not as a number:

$answer = '5'

"'5' -le 10       : $($answer -le 10)"
"[int]'5' -le 10  : $([int]$answer -le 10)"

Output:

'5' -le 10       : False
[int]'5' -le 10  : True

As text, ‘5’ comes after ’10’, so a range check lets 5 through. Convert the input first. -as [int] returns $null for anything that isn’t a number, instead of stopping with an error: