bashpipesubshell

why bash read command create a loop-local variable?


I wrote following bash script. The read command creates variable var. if $var==5 then break loop.

    seq 10 | while read -r var
    do
      echo "read: $var"
      if [[ $var == 5 ]]; then
        echo "break loop: $var"
        break
      fi
    done
    
    echo "after loop: $var"

Here is the output

read: 1
read: 2
read: 3
read: 4
read: 5
break loop: 5
after loop: 

My question is: why after loop, $var is empty?


Solution

  • The variable isn't loop-local, and everything related to read and loops here are just red herrings. The behavior you're seeing is because the pipe starts a subshell. If you get rid of the pipe and run this code instead:

        while read -r var
        do
          echo "read: $var"
          if [[ $var == 5 ]]; then
            echo "break loop: $var"
            break
          fi
        done < <(seq 10)
        
        echo "after loop: $var"
    

    Then it will print this instead:

    read: 1
    read: 2
    read: 3
    read: 4
    read: 5
    break loop: 5
    after loop: 5