Skip to main content
deleted 42 characters in body
Source Link
ilkkachu
  • 147.8k
  • 16
  • 268
  • 441

[[ -n "$line" ]] tests if $line (the variable just read by read) is not empty. It's useful since read returns a success if and only if it sees a newline character before the end-of-file. If the input contains a line fragment without a newline in the end, this test will catch that, and the loop will process that final incomplete line, too. Without the extra test, such an incomplete line would be read into $line, but ignored by the loop.

I said "incomplete line", since the POSIX definitions of a text file and a line require a newline at the end of each line. Other tools than read can also care, e.g. wc -l counts the newline characters, and so ignores a final incomplete line. See e.g. What's the point in adding a new line to the end of a file? and Why should text files end with a newline? on SO.

The cmd1 || cmd2 construct is of course just like the equivalent in C. The second command runs if the first returns a falsy status, and the result is the exit status of the last command that executed.

Compare:

$ printf 'foo\nbar' | ( while read line; do
                            echo "in loop: $line"
                        done
                        echo "finally: $line"
                      )
# prints:
#   in loop: foo
#   finally: bar

and

$ printf 'foo\nbar' | ( while read line || [[ -n $line ]]; do 
                            echo "in loop: $line"
                        done
                        echo "finally: $line"
                      )
# prints:
#   in loop: foo
#   in loop: bar
#   finally: 

[[ -n "$line" ]] tests if $line (the variable just read by read) is not empty. It's useful since read returns a success if and only if it sees a newline character before the end-of-file. If the input contains a line fragment without a newline in the end, this test will catch that, and the loop will process that final incomplete line, too. Without the extra test, such an incomplete line would be read into $line, but ignored by the loop.

I said "incomplete line", since the POSIX definitions of a text file and a line require a newline at the end of each line. Other tools than read can also care, e.g. wc -l counts the newline characters, and so ignores a final incomplete line. See e.g. What's the point in adding a new line to the end of a file? and Why should text files end with a newline? on SO.

The cmd1 || cmd2 construct is of course just like the equivalent in C. The second command runs if the first returns a falsy status, and the result is the exit status of the last command that executed.

Compare:

$ printf 'foo\nbar' | ( while read line; do
                            echo "in loop: $line"
                        done
                        echo "finally: $line"
                      )
# prints:
#   in loop: foo
#   finally: bar

and

$ printf 'foo\nbar' | ( while read line || [[ -n $line ]]; do 
                            echo "in loop: $line"
                        done
                        echo "finally: $line"
                      )
# prints:
#   in loop: foo
#   in loop: bar
#   finally: 

[[ -n "$line" ]] tests if $line (the variable just read by read) is not empty. It's useful since read returns a success if and only if it sees a newline character before the end-of-file. If the input contains a line fragment without a newline in the end, this test will catch that, and the loop will process that final incomplete line, too. Without the extra test, such an incomplete line would be read into $line, but ignored by the loop.

I said "incomplete line", since the POSIX definitions of a text file and a line require a newline at the end of each line. Other tools than read can also care, e.g. wc -l counts the newline characters, and so ignores a final incomplete line. See e.g. What's the point in adding a new line to the end of a file? and Why should text files end with a newline? on SO.

The cmd1 || cmd2 construct is of course just like the equivalent in C. The second command runs if the first returns a falsy status, and the result is the exit status of the last command that executed.

Compare:

$ printf 'foo\nbar' | ( while read line; do
                            echo "in loop: $line"
                        done
                        echo "finally: $line"
                      )
in loop: foo
finally: bar

and

$ printf 'foo\nbar' | ( while read line || [[ -n $line ]]; do 
                            echo "in loop: $line"
                        done
                        echo "finally: $line"
                      )
in loop: foo
in loop: bar
finally: 
brought syntax highlighting, fixed some formatting
Source Link
$ printf 'foo\nbar' | ( while read line; do echo "in loop: $line"; done;
                        echo "finally: $line" )
in loop: foo
finally: bar
$ printf 'foo\nbar' | ( while read line; do
                            echo "in loop: $line"
                        done
                        echo "finally: $line"
                      )
# prints:
#   in loop: foo
#   finally: bar
$ printf 'foo\nbar' | ( while read line || [[ -n $line ]]; do 
                           echo "in loop: $line"; done; 
                        echo "finally: $line" )
in loop: foo
in loop: bar
finally: 
$ printf 'foo\nbar' | ( while read line || [[ -n $line ]]; do 
                            echo "in loop: $line"
                        done
                        echo "finally: $line"
                      )
# prints:
#   in loop: foo
#   in loop: bar
#   finally: 
$ printf 'foo\nbar' | ( while read line; do echo "in loop: $line"; done;
                        echo "finally: $line" )
in loop: foo
finally: bar
$ printf 'foo\nbar' | ( while read line || [[ -n $line ]]; do 
                           echo "in loop: $line"; done; 
                        echo "finally: $line" )
in loop: foo
in loop: bar
finally: 
$ printf 'foo\nbar' | ( while read line; do
                            echo "in loop: $line"
                        done
                        echo "finally: $line"
                      )
# prints:
#   in loop: foo
#   finally: bar
$ printf 'foo\nbar' | ( while read line || [[ -n $line ]]; do 
                            echo "in loop: $line"
                        done
                        echo "finally: $line"
                      )
# prints:
#   in loop: foo
#   in loop: bar
#   finally: 
added 803 characters in body
Source Link
ilkkachu
  • 147.8k
  • 16
  • 268
  • 441

[[ -n "$line" ]] tests if $line (the variable just read by read) is not empty. It's useful since read returns a success if and only if it sees a newline character before the end-of-file. If the input contains a line fragment without a newline in the end, this test will catch that, and the loop will process that final incomplete line, too. Without the extra test, such an incomplete line would be read into $line, but ignored by the loop.

I said "incomplete line", since the POSIX definitions of a text file and a line require a newline at the end of each line. Other tools than read can also care, e.g. wc -l counts the newline characters, and so ignores a final incomplete line. See e.g. What's the point in adding a new line to the end of a file? and Why should text files end with a newline? on SO.

The cmd1 || cmd2 construct is of course just like the equivalent in C. The second command runs if the first returns a falsy status, and the result is the exit status of the last command that executed.

Compare:

$ printf 'foo\nbar' | ( while read line; do echo "in loop: $line"$line"; ;done;
 done ;                      echo "finally: $line" )
in loop: foo
finally: bar

and

$ printf 'foo\nbar' | ( while read line || [[ -n $line ]]; do 
                           echo "in loop: $line"$line"; ;done; done 
 ;                       echo "finally: $line" )
in loop: foo
in loop: bar
finally: 

[[ -n "$line" ]] tests if $line (the variable just read by read) is not empty. It's useful since read returns a success if and only if it sees a newline character before the end-of-file. If the input contains a line fragment without a newline in the end, this test will catch that, and the loop will process that final incomplete line, too. Without the extra test, such an incomplete line would be read into $line, but ignored by the loop.

The cmd1 || cmd2 construct is of course just like the equivalent in C. The second command runs if the first returns a falsy status, and the result is the exit status of the last command that executed.

Compare:

$ printf 'foo\nbar' | ( while read line; do echo "in loop: $line" ; done ; echo "finally: $line" )
in loop: foo
finally: bar

and

$ printf 'foo\nbar' | ( while read line || [[ -n $line ]]; do echo "in loop: $line" ; done ; echo "finally: $line" )
in loop: foo
in loop: bar
finally: 

[[ -n "$line" ]] tests if $line (the variable just read by read) is not empty. It's useful since read returns a success if and only if it sees a newline character before the end-of-file. If the input contains a line fragment without a newline in the end, this test will catch that, and the loop will process that final incomplete line, too. Without the extra test, such an incomplete line would be read into $line, but ignored by the loop.

I said "incomplete line", since the POSIX definitions of a text file and a line require a newline at the end of each line. Other tools than read can also care, e.g. wc -l counts the newline characters, and so ignores a final incomplete line. See e.g. What's the point in adding a new line to the end of a file? and Why should text files end with a newline? on SO.

The cmd1 || cmd2 construct is of course just like the equivalent in C. The second command runs if the first returns a falsy status, and the result is the exit status of the last command that executed.

Compare:

$ printf 'foo\nbar' | ( while read line; do echo "in loop: $line"; done;
                        echo "finally: $line" )
in loop: foo
finally: bar

and

$ printf 'foo\nbar' | ( while read line || [[ -n $line ]]; do 
                           echo "in loop: $line"; done;  
                        echo "finally: $line" )
in loop: foo
in loop: bar
finally: 
added 206 characters in body
Source Link
ilkkachu
  • 147.8k
  • 16
  • 268
  • 441
Loading
added 156 characters in body
Source Link
ilkkachu
  • 147.8k
  • 16
  • 268
  • 441
Loading
Source Link
ilkkachu
  • 147.8k
  • 16
  • 268
  • 441
Loading