What does `while read -r line || [[ -n $line ]]` mean?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
1
down vote

favorite












I found some code for reading input from a file a while ago, I believe from Stack Exchange, that I was able to adapt for my needs:



while read -r line || [[ -n "$line" ]]; do
if [[ $line != "" ]]
then
((x++));
echo "$x: $line"
<then do something with $line>
fi
done < "$1"


I'm reviewing my script now & trying to understand what it's doing ... I don't understand what this statement is doing:



while read -r line || [[ -n "$line" ]];



I understand that the -r option says that we're reading raw text into line, but I'm confused about the || [[ -n "$line" ]] portion of the statement. Can someone please explain what that is doing?










share|improve this question









New contributor




K. Hilbert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.























    up vote
    1
    down vote

    favorite












    I found some code for reading input from a file a while ago, I believe from Stack Exchange, that I was able to adapt for my needs:



    while read -r line || [[ -n "$line" ]]; do
    if [[ $line != "" ]]
    then
    ((x++));
    echo "$x: $line"
    <then do something with $line>
    fi
    done < "$1"


    I'm reviewing my script now & trying to understand what it's doing ... I don't understand what this statement is doing:



    while read -r line || [[ -n "$line" ]];



    I understand that the -r option says that we're reading raw text into line, but I'm confused about the || [[ -n "$line" ]] portion of the statement. Can someone please explain what that is doing?










    share|improve this question









    New contributor




    K. Hilbert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.





















      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      I found some code for reading input from a file a while ago, I believe from Stack Exchange, that I was able to adapt for my needs:



      while read -r line || [[ -n "$line" ]]; do
      if [[ $line != "" ]]
      then
      ((x++));
      echo "$x: $line"
      <then do something with $line>
      fi
      done < "$1"


      I'm reviewing my script now & trying to understand what it's doing ... I don't understand what this statement is doing:



      while read -r line || [[ -n "$line" ]];



      I understand that the -r option says that we're reading raw text into line, but I'm confused about the || [[ -n "$line" ]] portion of the statement. Can someone please explain what that is doing?










      share|improve this question









      New contributor




      K. Hilbert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      I found some code for reading input from a file a while ago, I believe from Stack Exchange, that I was able to adapt for my needs:



      while read -r line || [[ -n "$line" ]]; do
      if [[ $line != "" ]]
      then
      ((x++));
      echo "$x: $line"
      <then do something with $line>
      fi
      done < "$1"


      I'm reviewing my script now & trying to understand what it's doing ... I don't understand what this statement is doing:



      while read -r line || [[ -n "$line" ]];



      I understand that the -r option says that we're reading raw text into line, but I'm confused about the || [[ -n "$line" ]] portion of the statement. Can someone please explain what that is doing?







      read






      share|improve this question









      New contributor




      K. Hilbert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      K. Hilbert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited 15 mins ago









      muru

      34.4k579149




      34.4k579149






      New contributor




      K. Hilbert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 7 hours ago









      K. Hilbert

      83




      83




      New contributor




      K. Hilbert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      K. Hilbert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      K. Hilbert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.




















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          1
          down vote



          accepted










          [[ -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 'foonbar' | ( while read line; do echo "in loop: $line" ; done ; echo "finally: $line" )
          in loop: foo
          finally: bar


          and



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





          share|improve this answer






















          • A missing LF at EOF totally slipped my mind. Good catch on that...
            – brhfl
            5 hours ago










          • Thank you both for your answers ... that clears it up.
            – K. Hilbert
            5 hours ago

















          up vote
          1
          down vote













          It's a bit confusing as to why that would be there, but straightforward to explain what it does: || is an OR statement, and [[ -n returns true (success) as long as "$line" has a nonzero length. Here's what's confusing: while loops keep going while there's a successful (0) exit status. read continues to read lines and return a 0 exit status until it hits end of file -- even if those lines are blank. [[ -n "$line" ]] is only going to execute when read returns a nonzero exit code, at which point $line will be empty. Since the test returns true if $line is not empty, we're back to a nonzero exit, throwing us out of the while loop. As far as I can see, || [[ -n "$line" ]] doesn't actually accomplish anything. (As @ilkkachu pointed out, this will catch the odd final line of input that is missing its trailing newline. Note that such a file is not a valid text file, as that line is not a valid line)



          Something that is occasionally useful is to do while read -r line && [[ -n "$line" ]]. Using && (AND) means that the whole statement will only return a zero status if read is able to read a line, AND that line is not empty. It will cause the while loop to halt at the first empty line. If I had to make a guess, this snippet of code may have been adapted from one which did just that - and instead of simply removing the test, the author changed the && to ||.






          share|improve this answer






















            Your Answer








            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "106"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "",
            contentPolicyHtml: "",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );






            K. Hilbert is a new contributor. Be nice, and check out our Code of Conduct.









             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f478720%2fwhat-does-while-read-r-line-n-line-mean%23new-answer', 'question_page');

            );

            Post as a guest






























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            1
            down vote



            accepted










            [[ -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 'foonbar' | ( while read line; do echo "in loop: $line" ; done ; echo "finally: $line" )
            in loop: foo
            finally: bar


            and



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





            share|improve this answer






















            • A missing LF at EOF totally slipped my mind. Good catch on that...
              – brhfl
              5 hours ago










            • Thank you both for your answers ... that clears it up.
              – K. Hilbert
              5 hours ago














            up vote
            1
            down vote



            accepted










            [[ -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 'foonbar' | ( while read line; do echo "in loop: $line" ; done ; echo "finally: $line" )
            in loop: foo
            finally: bar


            and



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





            share|improve this answer






















            • A missing LF at EOF totally slipped my mind. Good catch on that...
              – brhfl
              5 hours ago










            • Thank you both for your answers ... that clears it up.
              – K. Hilbert
              5 hours ago












            up vote
            1
            down vote



            accepted







            up vote
            1
            down vote



            accepted






            [[ -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 'foonbar' | ( while read line; do echo "in loop: $line" ; done ; echo "finally: $line" )
            in loop: foo
            finally: bar


            and



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





            share|improve this answer














            [[ -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 'foonbar' | ( while read line; do echo "in loop: $line" ; done ; echo "finally: $line" )
            in loop: foo
            finally: bar


            and



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






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 5 hours ago

























            answered 6 hours ago









            ilkkachu

            53.2k780146




            53.2k780146











            • A missing LF at EOF totally slipped my mind. Good catch on that...
              – brhfl
              5 hours ago










            • Thank you both for your answers ... that clears it up.
              – K. Hilbert
              5 hours ago
















            • A missing LF at EOF totally slipped my mind. Good catch on that...
              – brhfl
              5 hours ago










            • Thank you both for your answers ... that clears it up.
              – K. Hilbert
              5 hours ago















            A missing LF at EOF totally slipped my mind. Good catch on that...
            – brhfl
            5 hours ago




            A missing LF at EOF totally slipped my mind. Good catch on that...
            – brhfl
            5 hours ago












            Thank you both for your answers ... that clears it up.
            – K. Hilbert
            5 hours ago




            Thank you both for your answers ... that clears it up.
            – K. Hilbert
            5 hours ago












            up vote
            1
            down vote













            It's a bit confusing as to why that would be there, but straightforward to explain what it does: || is an OR statement, and [[ -n returns true (success) as long as "$line" has a nonzero length. Here's what's confusing: while loops keep going while there's a successful (0) exit status. read continues to read lines and return a 0 exit status until it hits end of file -- even if those lines are blank. [[ -n "$line" ]] is only going to execute when read returns a nonzero exit code, at which point $line will be empty. Since the test returns true if $line is not empty, we're back to a nonzero exit, throwing us out of the while loop. As far as I can see, || [[ -n "$line" ]] doesn't actually accomplish anything. (As @ilkkachu pointed out, this will catch the odd final line of input that is missing its trailing newline. Note that such a file is not a valid text file, as that line is not a valid line)



            Something that is occasionally useful is to do while read -r line && [[ -n "$line" ]]. Using && (AND) means that the whole statement will only return a zero status if read is able to read a line, AND that line is not empty. It will cause the while loop to halt at the first empty line. If I had to make a guess, this snippet of code may have been adapted from one which did just that - and instead of simply removing the test, the author changed the && to ||.






            share|improve this answer


























              up vote
              1
              down vote













              It's a bit confusing as to why that would be there, but straightforward to explain what it does: || is an OR statement, and [[ -n returns true (success) as long as "$line" has a nonzero length. Here's what's confusing: while loops keep going while there's a successful (0) exit status. read continues to read lines and return a 0 exit status until it hits end of file -- even if those lines are blank. [[ -n "$line" ]] is only going to execute when read returns a nonzero exit code, at which point $line will be empty. Since the test returns true if $line is not empty, we're back to a nonzero exit, throwing us out of the while loop. As far as I can see, || [[ -n "$line" ]] doesn't actually accomplish anything. (As @ilkkachu pointed out, this will catch the odd final line of input that is missing its trailing newline. Note that such a file is not a valid text file, as that line is not a valid line)



              Something that is occasionally useful is to do while read -r line && [[ -n "$line" ]]. Using && (AND) means that the whole statement will only return a zero status if read is able to read a line, AND that line is not empty. It will cause the while loop to halt at the first empty line. If I had to make a guess, this snippet of code may have been adapted from one which did just that - and instead of simply removing the test, the author changed the && to ||.






              share|improve this answer
























                up vote
                1
                down vote










                up vote
                1
                down vote









                It's a bit confusing as to why that would be there, but straightforward to explain what it does: || is an OR statement, and [[ -n returns true (success) as long as "$line" has a nonzero length. Here's what's confusing: while loops keep going while there's a successful (0) exit status. read continues to read lines and return a 0 exit status until it hits end of file -- even if those lines are blank. [[ -n "$line" ]] is only going to execute when read returns a nonzero exit code, at which point $line will be empty. Since the test returns true if $line is not empty, we're back to a nonzero exit, throwing us out of the while loop. As far as I can see, || [[ -n "$line" ]] doesn't actually accomplish anything. (As @ilkkachu pointed out, this will catch the odd final line of input that is missing its trailing newline. Note that such a file is not a valid text file, as that line is not a valid line)



                Something that is occasionally useful is to do while read -r line && [[ -n "$line" ]]. Using && (AND) means that the whole statement will only return a zero status if read is able to read a line, AND that line is not empty. It will cause the while loop to halt at the first empty line. If I had to make a guess, this snippet of code may have been adapted from one which did just that - and instead of simply removing the test, the author changed the && to ||.






                share|improve this answer














                It's a bit confusing as to why that would be there, but straightforward to explain what it does: || is an OR statement, and [[ -n returns true (success) as long as "$line" has a nonzero length. Here's what's confusing: while loops keep going while there's a successful (0) exit status. read continues to read lines and return a 0 exit status until it hits end of file -- even if those lines are blank. [[ -n "$line" ]] is only going to execute when read returns a nonzero exit code, at which point $line will be empty. Since the test returns true if $line is not empty, we're back to a nonzero exit, throwing us out of the while loop. As far as I can see, || [[ -n "$line" ]] doesn't actually accomplish anything. (As @ilkkachu pointed out, this will catch the odd final line of input that is missing its trailing newline. Note that such a file is not a valid text file, as that line is not a valid line)



                Something that is occasionally useful is to do while read -r line && [[ -n "$line" ]]. Using && (AND) means that the whole statement will only return a zero status if read is able to read a line, AND that line is not empty. It will cause the while loop to halt at the first empty line. If I had to make a guess, this snippet of code may have been adapted from one which did just that - and instead of simply removing the test, the author changed the && to ||.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited 5 hours ago

























                answered 6 hours ago









                brhfl

                1634




                1634




















                    K. Hilbert is a new contributor. Be nice, and check out our Code of Conduct.









                     

                    draft saved


                    draft discarded


















                    K. Hilbert is a new contributor. Be nice, and check out our Code of Conduct.












                    K. Hilbert is a new contributor. Be nice, and check out our Code of Conduct.











                    K. Hilbert is a new contributor. Be nice, and check out our Code of Conduct.













                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f478720%2fwhat-does-while-read-r-line-n-line-mean%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    How to check contact read email or not when send email to Individual?

                    Displaying single band from multi-band raster using QGIS

                    How many registers does an x86_64 CPU actually have?