PowerShell Break and Continue in Loops Explained

PowerShell Break and Continue in Loops Explained

PowerShell Tips Editor 3 min read
PowerShell Break and Continue in Loops Explained

A search loop that scans a 10,000-item list for a specific entry does not need to continue after finding it — but without break, it does. Conversely, a processing loop that skips invalid records needs continue to move past bad data without stopping completely. Understanding PowerShell break continue loop control flow makes your loops both faster and more precise. This post covers both keywords in all loop types, labeled breaks for nested loops, and the important distinction when working with ForEach-Object.

Break Exits the Current Loop

break immediately exits the innermost loop it is placed in and continues execution after the loop’s closing brace. It works in foreach, for, while, and do-while loops:

$servers = Get-Content "C:\Scripts\servers.txt"
$target  = "ProdDB01"

foreach ($server in $servers) {
    if ($server -eq $target) {
        Write-Host "Found: $server"
        break   # Stop searching — no need to check remaining servers
    }
    Write-Host "Checking: $server"
}

Write-Host "Search complete"
Checking: Server01
Checking: Server02
Found: ProdDB01
Search complete

Continue Skips to Next Iteration

continue skips the rest of the current loop body and jumps directly to the next iteration. Use it to filter out records that do not meet a condition without nesting your processing logic in an if block:

$files = Get-ChildItem "C:\Logs" -File

foreach ($file in $files) {
    # Skip files smaller than 1 KB
    if ($file.Length -lt 1KB) { continue }

    # Skip files not matching expected naming pattern
    if ($file.Name -notmatch '^\d{8}_.*\.log$') { continue }

    Write-Host "Processing: $($file.Name)"
    # ... process file ...
}

Using Break in Switch Statements

break also exits switch blocks. In a switch, break prevents fall-through to subsequent matching cases:

$statusCode = 404

switch ($statusCode) {
    200 { Write-Host "OK"; break }
    301 { Write-Host "Moved Permanently"; break }
    404 { Write-Host "Not Found"; break }
    500 { Write-Host "Server Error"; break }
    default { Write-Host "Unknown status: $statusCode" }
}
Not Found

Labeled Breaks for Nested Loops

When you need to break out of an outer loop from inside a nested loop, use a loop label. Labels are placed immediately before the loop keyword with a colon:

$found = $false

:outerLoop foreach ($server in @('web01','web02','db01')) {
    foreach ($port in @(80, 443, 8080, 3389)) {
        $connected = Test-NetConnection -ComputerName $server -Port $port -InformationLevel Quiet -WarningAction SilentlyContinue
        if ($connected) {
            Write-Host "First open port: $server : $port"
            break outerLoop   # Break out of both loops
        }
    }
}

Write-Host "Search complete"

Break vs Return in Functions

break exits only the current loop; return exits the entire function. Inside a function, use return when you want to exit completely after finding a result:

function Find-FirstMatch {
    param([string[]]$List, [string]$Pattern)
    foreach ($item in $List) {
        if ($item -match $Pattern) {
            return $item   # Exits the function and returns the value
        }
    }
    return $null   # No match found
}

$result = Find-FirstMatch -List @('alpha','beta','gamma') -Pattern 'bet'
Write-Host "Found: $result"

Continue in ForEach-Object (Use Return)

This is a critical distinction: inside ForEach-Object (the cmdlet, using |), the keywords behave differently from the foreach statement:

# In ForEach-Object: use 'return' to skip to the next item (acts like 'continue')
Get-ChildItem "C:\Logs" | ForEach-Object {
    if ($_.Length -lt 1KB) { return }   # 'continue' equivalent in ForEach-Object
    Write-Host "Processing: $($_.Name)"
}

# 'break' inside ForEach-Object exits the ForEach-Object cmdlet entirely,
# not the outer loop or script — this is often not what you want.
# Use a flag variable or foreach statement when you need break behavior in a pipeline.

Common Errors and Fixes

  • Continue in ForEach-Object uses return not continue keyword. In the ForEach-Object cmdlet’s script block, continue works like break (it exits the cmdlet), while return works like continue (it skips to the next pipeline input). This is counter-intuitive. If you need loop-control semantics, use the foreach statement instead.
  • Break inside ForEach-Object exits the forEach cmdlet, not the outer loop. If you have a foreach statement that contains a ForEach-Object pipeline, a break inside the pipeline exits the ForEach-Object cmdlet but not the outer foreach statement. Use a flag variable and check it in the outer loop to propagate a break from inside a pipeline.

Related Cmdlets / See Also

Wrapping Up

Use break to exit a loop early when the goal is achieved, continue to skip invalid iterations, labeled breaks to exit nested loops, and — critically — return (not continue) inside ForEach-Object script blocks to skip to the next pipeline input. These distinctions separate clean, efficient loops from confusing behavior.

Send-Item -To