3

According the bash(1) man pages, when I run the following:

set -e
x=2
echo Start $x
while [ $((x--)) -gt 0 ]; do echo Loop $x; done | cat
echo End $x

The output will be:

Start 2
Loop 1
Loop 0
End 2

After the loop (runs as a subshell) the variable x reset to 2. But if I remove the pipe the x will be updated:

Start 2
Loop 1
Loop 0
End -1

I need to change the x but, I need the pipe too. Any idea how to get around this problem?

4
  • 1
    What does | cat do here? Does it do something meaningful? Commented Jun 4, 2013 at 14:45
  • 1
    stackoverflow.com/q/4667509/900873 Commented Jun 4, 2013 at 14:54
  • @devnull, I think it's just there for illustration: that adding a pipe to anything will mean the while loop is run in a subshell, and any changes to variable $x are lost when the subshell ends. Commented Jun 4, 2013 at 15:09
  • Yes, The real loop is long. Inside the loop I have some lines like: ping -c1 Machine || STOP="YES" At the end of the loop I grep(1) out the lines of "icmp_seq=" Commented Jun 5, 2013 at 6:41

1 Answer 1

3

bash always (at least as of 4.2) runs all non-rightmost parts of a pipeline in a subshell. If the value of x needs to change in the calling shell, you must rewrite your code to avoid the pipeline.

One horrible-looking example:

# If you commit to one bash feature, may as well commit to them all:
#   Arithmetic compound: (( x-- > 0 ))
#   Process substitution: > >( cat )
while (( x-- > 0 )); do echo Loop $x; done > >( cat )
Sign up to request clarification or add additional context in comments.

2 Comments

@udi, read about process substitution here
@chepner, Thank you very much! I had a little typo and now it works.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.