9
unset v
function f {
  v=1
}
f | cat
echo v=$v
f 
echo v=$v

Why does piping (to any command) prevent the first echo command from printing 1? The second echo prints 1. I'm using a bash shell. I can see this by copy/paste or by running this as a script.

1 Answer 1

15

All components of a pipeline (if more than one) are executed in a subshell, and their variable assignments do not persist to the main shell.

The reason for this is that bash does not support real multithreading (with concurrent access to variables), only subprocesses which run in parallel.


How to avoid this:

You have to do any variable assignments you want to retain in the main bash process (or find some way to transfer them there). The bash way of doing this would be not to use a pipe, but use process substitution instead:

f > >( cat )

Of course, this will not help if you need to do variable assignments in both processes of a pipe. Then you have to think of a better mechanism instead (maybe coprocesses, and output the variables somewhere?)

3
  • 1
    Actually, this applies to all elements of a pipe including the last one. Commented Jun 6, 2011 at 19:37
  • Hmm, strange ... where did I get the wrong impression? Thanks, I changed this. Commented Jun 6, 2011 at 20:25
  • 1
    ŭlo: Some shells (ksh and zsh I think, but not bash) run the last element of the pipeline in the main shell process.
    – camh
    Commented Jun 6, 2011 at 21:13

Not the answer you're looking for? Browse other questions tagged or ask your own question.