0

My bash version is GNU bash, version 4.3.42(1)-release (x86_64-pc-linux-gnu). This is a simplified version of my script:

#!/bin/bash
touch a.ecl
touch b.ecl

function_syntaxCheckFileName()
{
  return 1 # 1 syntax error
}

tmpTotalErrors=0
result=0
echo "DEBUG Starting loop"
find . -name '*.ecl' -print0 | while read -d $'\0' file
do 
  echo " DEBUG - FILE=$file"
  echo "  DEBUG0 tmpTotalErrors=$tmpTotalErrors --- result=$result"
  function_syntaxCheckFileName "$file" 
  result=$?
  echo "  DEBUG1 tmpTotalErrors=$tmpTotalErrors --- result=$result"
  tmpTotalErrors=$((tmpTotalErrors + result)) 
  echo "  DEBUG2 tmpTotalErrors=$tmpTotalErrors --- result=$result"
done

echo "DEBUG3 tmpTotalErrors=$tmpTotalErrors"

It is designed to be run in path with spaces so I use this iteration

find . -name '*.ecl' -print0 | while read -d $'\0' file

The output is this:

DEBUG Starting loop
 DEBUG - FILE=./a.ecl
  DEBUG0 tmpTotalErrors=0 --- result=0
  DEBUG1 tmpTotalErrors=0 --- result=1
  DEBUG2 tmpTotalErrors=1 --- result=1
 DEBUG - FILE=./b.ecl
  DEBUG0 tmpTotalErrors=1 --- result=1
  DEBUG1 tmpTotalErrors=1 --- result=1
  DEBUG2 tmpTotalErrors=2 --- result=1
DEBUG3 tmpTotalErrors=0

My problem is that tmpTotalErrors lose its value. It was supposed to be 2 and it is 0.

So my questions are:

  1. How can I my script work?
  2. Why is failing?

1 Answer 1

3

Rewrite the loop to avoid subshel by using set +m; shopt -s lastpipe

 #!/bin/bash
set +m 
shopt -s lastpipe
touch a.ecl
touch b.ecl

function_syntaxCheckFileName()
{
  return 1 # 1 syntax error
}

tmpTotalErrors=0
result=0
echo "DEBUG Starting loop"

find . -name '*.ecl' -print0 | while read -d $'\0' file
do 
  echo " DEBUG - FILE=$file"
  echo "  DEBUG0 tmpTotalErrors=$tmpTotalErrors --- result=$result"
  function_syntaxCheckFileName "$file" 
  result=$?
  echo "  DEBUG1 tmpTotalErrors=$tmpTotalErrors --- result=$result"
  tmpTotalErrors=$((tmpTotalErrors + result)) 
  echo "  DEBUG2 tmpTotalErrors=$tmpTotalErrors --- result=$result"
done
echo "DEBUG3 tmpTotalErrors=$tmpTotalErrors"

It's failing because changes in subshell don't reflect in the parent shell.

Also see this Bash FAQ entry: I set variables in a loop that's in a pipeline. Why do they disappear after the loop terminates? Or, why can't I pipe data to read? which discusses a number of alternative solutions.

Sign up to request clarification or add additional context in comments.

9 Comments

I tried your code and it is not entering in the loop. Output is DEBUG Starting loop DEBUG3 tmpTotalErrors=0
Changed with same result. My line now is while read -r -d '' file Could you update your answer?
@OscarFoley Since your bash support lastpipe, can you try to use set +m; shopt -s lastpipe in your script as it is (without rewriting anything else)?
Never seen that shopt... how can I use it? Thanks a lot for the help btw...
@OscarFoley See the linked wiki which explains it. You just need to add the two lines I mentioned in my previous comment into your script?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.