0

Problem

My bash script loops through a bunch of files and if it finds an unexpected file that contains some text, it sets an error flag and is supposed to exit the loop. The problem is that when i evaluate the error condition after the loop, the error flag isn't set properly. I can't seem to see where the bug is.

Code

#!/bin/sh
valid=1
grep -rs -L 'bogustext' * | while read line; do
    echo "Processing file '$line'"
    if [ "$line" != "arc/.keep" ] && [ "$line" != "arc/prp/lxc" ] && [ "$line" != "arc/lbb/lxc" ]; then
        valid=0
        echo "just set it to zero - $valid"
        break 2
    fi
done
echo "$valid"
if [ "$valid"  -eq 0 ]; then
    echo "1..1"
    echo "not ok $line invis malformed"
else
    echo "1..1"
    echo "ok"
fi

Here's the output which shows the problem / bug. As you can see, there is an extra file in the list that contains the bogus string "arc/ttp". The script sets the "valid" variable to 0 but by the time I'm ready to evaluate it to display the right status, it's still the original value.

lab-1:/var/vrior# sh test.sh
Processing file 'arc/.keep'
Processing file 'arc/prp/lxc'
Processing file 'arc/lbb/lxc'
Processing file 'arc/ttp'
just set it to zero - 0
1
1..1
ok

What I've tried so far I'm currently googling to see if in Bash there's local variables vs. global. Not too sure, but if you see my bug, please let me know.

dot
  • 14,928
  • 41
  • 110
  • 218
  • Also, [BashFAQ/024](http://mywiki.wooledge.org/BashFAQ/024): "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?" – Benjamin W. Aug 31 '17 at 14:29
  • Thanks @BenjaminW. Problem is that i'm a noob with shell scripting so I didn't even know what do search for. Didn't even know "|" was called a pipeline. But now I do! Thanks for the link – dot Aug 31 '17 at 14:33

1 Answers1

2

Pipes create subshells, so $valid inside the loop refers to a new variable, which disappears before you try and use it.

Since you've tagged bash, then you can use a process substitution instead of the pipe:

while read line; do
    echo "Processing file '$line'"
    if [ "$line" != "arc/.keep" ] && [ "$line" != "arc/prp/lxc" ] && [ "$line" != "arc/lbb/lxc" ]; then
        valid=0
        echo "just set it to zero - $valid"
        break 2
    fi
done < <(grep -rs -L 'bogustext' *)
Tom Fenech
  • 72,334
  • 12
  • 107
  • 141
  • Thanks Tom. I'm giving this a try but are you supposd to have "< <"? there's a space embedded between? cuz i'm getting an error about "Unexpected redirection" on this line – dot Aug 31 '17 at 14:19
  • @dot you should make sure you're using bash. Use `#!/bin/bash` at the top of your script. If you need to do this with another shell it can be achieved via other means. – Tom Fenech Aug 31 '17 at 14:22