BASH scripting - WHILE loop variations - Variable scope

Hello dear Reader,

Could you please help me understand why the variable COUNTER does not keep its value outside the while loop as seen in case A but keeps it in case B? The difference is how the while loop gets its input.

Imagine you have file students.csv

# ./students.csv
John, Doe
Alice, Brown
David, Rosendorf

Case A:

SOURCE_FILE="students.csv"
COUNTER=0

cat $SOURCE_FILE | while IFS="," read FIRST LAST
do
    (( COUNTER++ ))
done

echo $COUNTER
# COUNTER = 0

Case B:

SOURCE_FILE="students.csv"
COUNTER=0

while IFS="," read FIRST LAST
do
    (( COUNTER++ ))
done < $SOURCE_FILE

echo $COUNTER
# COUNTER = 3

I think you forgot to use the read command here

Edit: like this
while IFS=“,” read -r FIRST LAST

Thanks for mentioning that.
That, however, does not change the case and the question remains.

I suppose it creates a sub-shell where the COUNTER is not seen so it creates local COUNTER… but why and where can I read more about this?

Different results on my side…

Could you try? :

# names.csv
John, Doe
Alice, Brown
David, Rosendorf
# while_test.sh
#!/bin/bash

COUNTER_A=0
COUNTER_B=0
FILE="names.csv"

cat $FILE | while IFS="," read LINE
do
        (( COUNTER_A++ ))
done
echo "COUNTER_A: $COUNTER_A"

while IFS="," read LINE
do
        (( COUNTER_B++ ))
done < $FILE
echo "COUNTER_B: $COUNTER_B"


I apologize. You are correct, the first one with COUNTER_A will not work because the inner portion of the while loop is running in a sub shell. You can get what you want by wrapping every after the pipe in { and }.

#!/bin/bash

COUNTER_A=0
COUNTER_B=0
FILE="students.csv"

cat $FILE |
{
  while IFS="," read -r LINE
  do
    (( COUNTER_A++ ))
  done
  echo "COUNTER_A:" $COUNTER_A
}

while IFS="," read -r LINE
do
  (( COUNTER_B++ ))
done < $FILE
echo "COUNTER_B: $COUNTER_B"