continue — Skip a loop iteration in bash, zsh, fish, PowerShell, and cmd across all 5 shells
Equivalents in every shell
for i in 1 2 3; do [ "$i" = "2" ] && continue; echo "$i"; donebash builtin. `continue N` skips to the next iteration of the N-th enclosing loop. Works in `for`, `while`, `until`, `select`. Like `break`, can be called from a function invoked inside a loop.
for i in 1 2 3; do [[ $i = 2 ]] && continue; echo $i; donezsh builtin, same semantics as bash with `continue N`. Works in `repeat`, `for`, `while`, `until`, `select`.
for i in 1 2 3; if test $i = 2; continue; end; echo $i; endfish builtin. Single-level only — NO `continue N`. To skip multiple levels, restructure with flag variables or extract inner logic to a function with early return.
foreach ($i in 1..3) { if ($i -eq 2) { continue }; $i }pwsh keyword. Supports LABELED continue: `:outer foreach (...) { foreach (...) { continue outer } }` skips to the next iteration of the outer loop. Unique among shells — same idiom as labeled break.
for %i in (1 2 3) do (if not "%i"=="2" echo %i)cmd has NO `continue` keyword. The idiom is to invert the condition and skip the loop body conditionally: `if NOT condition (loop_body)`. For complex bodies, factor into a `call :subroutine` and `goto :continue_label` at the top.
Worked examples
Process all files except those starting with a dot
for f in *; do [[ "$f" == .* ]] && continue; echo "$f"; doneforeach ($f in Get-ChildItem) { if ($f.Name -like ".*") { continue }; $f.Name }Skip iterations of an outer loop based on inner condition (labeled continue)
:outer foreach ($file in Get-ChildItem *.log) { foreach ($line in Get-Content $file) { if ($line -match "ABORT") { continue outer } } "$($file.Name) is clean" }for f in *.log; do skip=0; while IFS= read -r line; do if [[ "$line" == *ABORT* ]]; then skip=1; break; fi; done < "$f"; [ "$skip" = "1" ] && continue; echo "$f is clean"; doneSkip empty lines while reading a config file
while IFS= read -r line; do [ -z "$line" ] && continue; echo "$line"; done < config.txtwhile read -l line; if test -z "$line"; continue; end; echo $line; end < config.txtGet-Content config.txt | ForEach-Object { if ([string]::IsNullOrWhiteSpace($_)) { return }; $_ }Gotchas
- fish has NO multi-level `continue N` — same as `break`. Restructure with flag variables or extract logic to a function.
- pwsh inside `ForEach-Object` (the pipeline cmdlet, not the foreach keyword): `continue` and `break` behave DIFFERENTLY. Inside a `ForEach-Object` script block, `return` skips the current item (analogue of `continue`); `break` terminates the entire pipeline. The `foreach` KEYWORD has the normal `continue`/`break` semantics. This is a famous footgun — read up on the distinction before mixing the two forms.
- bash `continue` in a subshell-loop (`echo X | while read; do continue; done`) only affects the subshell's loop. Parent-loop `continue` from inside a subshell pipeline doesn't work — the subshell exits, parent loop continues normally.
- cmd lacks `continue` entirely. The `if NOT condition ()` inversion handles simple cases; complex skip-logic requires factoring loop bodies into subroutines.
- In an `until` loop, `continue` jumps back to the condition test — same as in `while`. The negation in `until` doesn't affect how `continue` flows; the loop continues until the condition becomes true.