Shell: while loops and variables

A common idiom in shell scripting is to tweak the value of IFS (internal field separator) while reading lines of input:

while IFS= read -r line
    # ...

This leads to questions about IFS itself and the -r flag, and there are plenty of good answers out there. I’d like to focus, however, on the syntax of IFS= and it’s location in the above line.

Shell variables can be assigned and referenced:

> var=A
> echo $var

Sometimes you want to set a variable for the duration of a single command:

> name=Bob bash -c 'echo $name'
> echo $name

At first glance, you might expect the first line of our while loop to look like:

IFS= while read -r line

but this causes a syntax error. In the name=Bob example, our entire line consisted of a single simple command, defined as

a sequence of optional variable assignments and redirections, in any sequence, optionally followed by words and redirections, terminated by a control operator.

The while loop, however, is a compound command, with the format:

while compound-list-1

with compound-list-1 being a sequence of lists. A list is defined as

a sequence of one or more AND-OR lists separated by the operators ‘;’ and ‘&’.

with an AND-OR list being

a sequence of one or more pipelines separated by the operators “&&” and “   ” .

A pipeline, in turn, has the format:

[!] command1 [ command2 …]

It feels like we’re going in circles, but the long and short of it is that we can view

while IFS= read -r line


while simple-command

Note that this means we’re setting IFS to a temporary value only during the read command, not during the body of the loop.

To make this a little more concrete, here’s a script I’ve called


tester() {
  echo "var in tester: $var"
  (( $i > 0 ))

echo -e "var before loop: $var\n"

while var=B tester; do
  let i-=1
  echo "var in loop: $var"

echo -e "\nvar after loop: $var"

The result:

> bash
var before loop: A

var in tester: B
var in loop: A
var in tester: B

var after loop: A