This loop only ever runs once — check the list expression

`for x in "$onething"` iterates a single fixed value. SC2043 flags for-loops whose list clearly has just one item.

Problem

A `for` loop whose word list is a single quoted string, a single variable known to hold one value, or a literal with no expansion at all will only ever execute its body once. This is frequently a sign that the author meant to iterate over multiple items — an array, a list of files, or the positional parameters — but wrote something that evaluates to just one value. It is not necessarily a bug (sometimes a one-shot "loop" is used deliberately so `break`/`continue` can be reused), but in most reported cases it indicates a missing `$@`, missing array expansion, or a typo.

Bad

name="single value"
for x in "$name"; do
  process "$x"
done

Good

names=("first value" "second value")
for x in "${names[@]}"; do
  process "$x"
done

Explanation

Once the list expression genuinely contains multiple words — an unquoted glob, `"$@"`, or `"${array[@]}"` — the loop iterates as expected. If a single-item loop really is intentional (e.g. for early `break` logic), an `if` statement is usually clearer and avoids the warning.

Related

SC2068

SC2066

SC2231

When It Matters

for x in "$list" or for x in $(echo "$one_thing") iterates exactly once, which means the loop is decoration around a single call. Usually the author intended to iterate a list and quoted it into a single word, or built the list in a way that collapsed it. A loop that runs once is not an error, so nothing complains at runtime — the script simply processes the first item and reports success.

Second Example

Note

Brace expansion happens before variable expansion, so {1..$n} does not work — use seq or a C-style loop for a dynamic range.

Exceptions

A single-iteration loop is sometimes a deliberate placeholder for a list that will grow, or a way to get a break target. Both are clearer written as a comment plus straight-line code, or as a while true with an explicit break.

Faq

Q

How do I loop over a dynamic range?

A

for (( i = 1; i <= n; i++ )) in Bash, or for i in $(seq 1 "$n") when you need POSIX compatibility.

Q

Why does {1..$n} print literally?

A

Brace expansion is performed before parameter expansion, so the shell never sees a number there.

Q

How do I iterate the lines of a variable?

A

Feed it to a read loop with a here-string: while IFS= read -r line; do ...; done <<< "$text".