La explicación correcta ya ha sido dada por jsbillings y geekosaur , pero permítanme ampliarlo un poco.
En la mayoría de los shells, incluido bash, cada lado de una tubería se ejecuta en un subshell, por lo que cualquier cambio en el estado interno del shell (como el establecimiento de variables) permanece limitado a ese segmento de una tubería. La única información que puede obtener de una subshell es lo que genera (a la salida estándar y otros descriptores de archivo) y su código de salida (que es un número entre 0 y 255). Por ejemplo, el siguiente fragmento imprime 0:
a=0; a=1 | a=2; echo $a
En ksh (las variantes derivadas del código AT&T, no las variantes pdksh / mksh) y zsh, el último elemento de una canalización se ejecuta en el shell principal. (POSIX permite ambos comportamientos). Por lo tanto, el fragmento anterior imprime 2.
Una expresión útil es incluir la continuación del ciclo while (o lo que sea que tenga en el lado derecho de la tubería, pero un ciclo while es realmente común aquí) en la tubería:
cat junk | {
while read var ; do x=55 ; done
echo x=$x
}