A blog about my experience in the IT world.

"Pipeculiar" WHILE behavior in ShellScript

December 13, 2013

While doing some scripting in shell I noticed an odd behavior, i was losing the value of my variable, digging around, i found that although the value was correct inside the while cycle, as soon as it finished the value was lost.
An example of such behavior is the following statement:

user@localhost:[/tmp]$ FICH=file.txt
user@localhost:[/tmp]$ echo "this is dog" > $FICH
user@localhost:[/tmp]$ cat $FICH | while read line; do var="$line";  echo "Inside: $var"; done
Inside: this is dog
user@localhost:[/tmp]$ echo "Outside: $var"
Outside:

Why this happened wasn't at all clear, but after some searching was done this piece of information shed light on the subject:
command | while read var1 var2 ...; do
   # process each line, using variables as parsed into $var1, $var2, etc
   # (note that this is a subshell: var1, var2 etc will not be available
   # after the while loop terminates)
   done
Using the pipe to send stdin to the while cycle, was creating a subshell where variable were assign the correct value, but as the while finished so did the subshell causing the values to be lost.
A quick modification to the to method of sending stdin to while, redirection instead of pipes, fixed the issue:
user@localhost:[/tmp]$ while read line; do var="$line";  echo "Inside: $var"; done < $FICH
Inside: this is dog
user@localhost:[/tmp]$ echo "Outside: $var"
Outside: this is dog
user@localhost:[/tmp]$

The reason can be found here:
A pipe is there to hook the stdout of one program to the stdin or another one. Two processes, possibly two shells.
When you do redirection (> and <), all you are doing is remapping stdin (or stdout) to a file. reading/writing a file can be done without another process or shell.