views:

291

answers:

4

I can't for the life of me see why I can not read the postPrioity outside the while loop. I tried "export postPrioity="500"" still didn't work.

Any ideas?

-- or in plan text --

#!/bin/bash
cat "/files.txt" | while read namesInFile; do 
   postPrioity="500"
   #This one shows the "$postPrioity" varible, as '500'
   echo "weeeeeeeeee ---> $postPrioity <--- 1"
done
   #This one comes up with "" as the $postPrioity varible. GRRR
   echo "weeeeeeeeee ---> $postPrioity <--- 2"

OUTPUT: (I only have 3 file names in files.txt)

weeeeeeeeee ---> 500 <--- 1
weeeeeeeeee ---> 500 <--- 1
weeeeeeeeee ---> 500 <--- 1
weeeeeeeeee --->  <--- 2
+2  A: 

I never thought about this before, but I'm guessing that the pipe/loop creates a child process shell, which naturally can't affect the environment of its parent. This is really unfortunate, because I really like the pipe/loop construct.

Jefromi
+7  A: 

The pipe operator creates a subshell, see BashPitfalls and BashFAQ. Solution: Don't use cat, it's useless anyway.

#!/bin/bash
postPriority=0
while read namesInFile
do   
    postPrioity=500
    echo "weeeeeeeeee ---> $postPrioity <--- 1"
done < /files.txt
echo "weeeeeeeeee ---> $postPrioity <--- 2"
Philipp
Thanks for confirming my guess! I think some of the other workarounds mentioned at BashFAQ (e.g. command grouping) are better bets, though - often your pipeline isn't meaningless.
Jefromi
Of course pipelines aren't meaningless in every case, but the construct “cat file | …” should in most cases be replaced by “… < file”. see e.g. the Bash Guide: http://mywiki.wooledge.org/BashGuide#BashGuide.2BAC8-Practices.2BAC8-DontEverDoThese.Don.27t_Ever_Do_These
Philipp
Never knew this, thou I knew a little about subshell's.But yeah ill keep this in mind now, and will have a read on those sites, thanks.
Mint
+4  A: 

As a complement to Philipp's response, in case you MUST use a pipe (and as he pointed out, in your example you don't need cat), you can put all the logic in the same side of the pipe:


command | {
  while read line; do
    variable=value
  done
  # Here $variable exists
  echo $variable
}
# Here it doesn't

Idelic
A: 

Alternatively use process substitution:

while read line do variable=value done