Bash “for” loop without a “in foo bar…” part

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











up vote
21
down vote

favorite
3












I was recently looking at some code that confused me because it works and I didn't expect it to. The code reduces to this example



#!/bin/bash
for var;
do
echo "$var"
done


When run with command line arguments is prints them



$ ./test a b c
a
b
c


It is this, that is (to me) unexpected. Why does this not result in an error because var is undefined ? Is using this considered 'good practice' ?







share|improve this question


























    up vote
    21
    down vote

    favorite
    3












    I was recently looking at some code that confused me because it works and I didn't expect it to. The code reduces to this example



    #!/bin/bash
    for var;
    do
    echo "$var"
    done


    When run with command line arguments is prints them



    $ ./test a b c
    a
    b
    c


    It is this, that is (to me) unexpected. Why does this not result in an error because var is undefined ? Is using this considered 'good practice' ?







    share|improve this question
























      up vote
      21
      down vote

      favorite
      3









      up vote
      21
      down vote

      favorite
      3






      3





      I was recently looking at some code that confused me because it works and I didn't expect it to. The code reduces to this example



      #!/bin/bash
      for var;
      do
      echo "$var"
      done


      When run with command line arguments is prints them



      $ ./test a b c
      a
      b
      c


      It is this, that is (to me) unexpected. Why does this not result in an error because var is undefined ? Is using this considered 'good practice' ?







      share|improve this question














      I was recently looking at some code that confused me because it works and I didn't expect it to. The code reduces to this example



      #!/bin/bash
      for var;
      do
      echo "$var"
      done


      When run with command line arguments is prints them



      $ ./test a b c
      a
      b
      c


      It is this, that is (to me) unexpected. Why does this not result in an error because var is undefined ? Is using this considered 'good practice' ?









      share|improve this question













      share|improve this question




      share|improve this question








      edited Jan 15 at 19:09









      Gilles

      506k11910021529




      506k11910021529










      asked Jan 15 at 16:55









      user270650

      1063




      1063




















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          26
          down vote













          for loops loop on the positional parameters if no in value1 value2... part is specified in all Bourne-like shells.



          That was already the case in the Bourne shell from the late 70s, though in the Bourne shell, you'd need to omit that ; (you can also use for i do (except in some old ash versions where you need a newline before the do)).



          See What is the purpose of the "do" keyword in Bash for loops? for more information including more surprising variants.



          Doing:



          for i
          do
          something with "$i"
          done


          is good practice. It's slightly more portable/reliable than the usually equivalent:



          for i in "$@"; do
          something with "$i"
          done


          for which the Bourne shell, ksh88 have some issues under some conditions (like when $# is 0 in some versions of the Bourne shell (which $1+"$@" instead of "$@" can work around) or when $IFS doesn't contain the space character in Bourne and ksh88), or when the nounset option is enabled and $# is 0 in some versions of some shells including bash (again with $1+"$@" as a work-around).






          share|improve this answer






















          • Had to read this thrice before my brain decided to stop editing out the repeated 'loop' at the start
            – Three Diag
            Jan 16 at 12:04

















          up vote
          21
          down vote













          This is the default behavior, yes. It is documented in the help of the for keyword:



          terdon@tpad ~ $ help for
          for: for NAME [in WORDS ... ] ; do COMMANDS; done
          Execute commands for each member in a list.

          The `for' loop executes a sequence of commands for each member in a
          list of items. If `in WORDS ...;' is not present, then `in "$@"' is
          assumed. For each element in WORDS, NAME is set to that element, and
          the COMMANDS are executed.

          Exit Status:
          Returns the status of the last command executed.


          So, when you don't give it a list to iterate over, it will default to iterating over $@, the array of positional parameters (a, b and c in your example).



          And this behavior is defined by POSIX so yes, it is considered "good practice" as far as that goes.






          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: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );








             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f417292%2fbash-for-loop-without-a-in-foo-bar-part%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
            26
            down vote













            for loops loop on the positional parameters if no in value1 value2... part is specified in all Bourne-like shells.



            That was already the case in the Bourne shell from the late 70s, though in the Bourne shell, you'd need to omit that ; (you can also use for i do (except in some old ash versions where you need a newline before the do)).



            See What is the purpose of the "do" keyword in Bash for loops? for more information including more surprising variants.



            Doing:



            for i
            do
            something with "$i"
            done


            is good practice. It's slightly more portable/reliable than the usually equivalent:



            for i in "$@"; do
            something with "$i"
            done


            for which the Bourne shell, ksh88 have some issues under some conditions (like when $# is 0 in some versions of the Bourne shell (which $1+"$@" instead of "$@" can work around) or when $IFS doesn't contain the space character in Bourne and ksh88), or when the nounset option is enabled and $# is 0 in some versions of some shells including bash (again with $1+"$@" as a work-around).






            share|improve this answer






















            • Had to read this thrice before my brain decided to stop editing out the repeated 'loop' at the start
              – Three Diag
              Jan 16 at 12:04














            up vote
            26
            down vote













            for loops loop on the positional parameters if no in value1 value2... part is specified in all Bourne-like shells.



            That was already the case in the Bourne shell from the late 70s, though in the Bourne shell, you'd need to omit that ; (you can also use for i do (except in some old ash versions where you need a newline before the do)).



            See What is the purpose of the "do" keyword in Bash for loops? for more information including more surprising variants.



            Doing:



            for i
            do
            something with "$i"
            done


            is good practice. It's slightly more portable/reliable than the usually equivalent:



            for i in "$@"; do
            something with "$i"
            done


            for which the Bourne shell, ksh88 have some issues under some conditions (like when $# is 0 in some versions of the Bourne shell (which $1+"$@" instead of "$@" can work around) or when $IFS doesn't contain the space character in Bourne and ksh88), or when the nounset option is enabled and $# is 0 in some versions of some shells including bash (again with $1+"$@" as a work-around).






            share|improve this answer






















            • Had to read this thrice before my brain decided to stop editing out the repeated 'loop' at the start
              – Three Diag
              Jan 16 at 12:04












            up vote
            26
            down vote










            up vote
            26
            down vote









            for loops loop on the positional parameters if no in value1 value2... part is specified in all Bourne-like shells.



            That was already the case in the Bourne shell from the late 70s, though in the Bourne shell, you'd need to omit that ; (you can also use for i do (except in some old ash versions where you need a newline before the do)).



            See What is the purpose of the "do" keyword in Bash for loops? for more information including more surprising variants.



            Doing:



            for i
            do
            something with "$i"
            done


            is good practice. It's slightly more portable/reliable than the usually equivalent:



            for i in "$@"; do
            something with "$i"
            done


            for which the Bourne shell, ksh88 have some issues under some conditions (like when $# is 0 in some versions of the Bourne shell (which $1+"$@" instead of "$@" can work around) or when $IFS doesn't contain the space character in Bourne and ksh88), or when the nounset option is enabled and $# is 0 in some versions of some shells including bash (again with $1+"$@" as a work-around).






            share|improve this answer














            for loops loop on the positional parameters if no in value1 value2... part is specified in all Bourne-like shells.



            That was already the case in the Bourne shell from the late 70s, though in the Bourne shell, you'd need to omit that ; (you can also use for i do (except in some old ash versions where you need a newline before the do)).



            See What is the purpose of the "do" keyword in Bash for loops? for more information including more surprising variants.



            Doing:



            for i
            do
            something with "$i"
            done


            is good practice. It's slightly more portable/reliable than the usually equivalent:



            for i in "$@"; do
            something with "$i"
            done


            for which the Bourne shell, ksh88 have some issues under some conditions (like when $# is 0 in some versions of the Bourne shell (which $1+"$@" instead of "$@" can work around) or when $IFS doesn't contain the space character in Bourne and ksh88), or when the nounset option is enabled and $# is 0 in some versions of some shells including bash (again with $1+"$@" as a work-around).







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jan 16 at 12:29

























            answered Jan 15 at 17:00









            Stéphane Chazelas

            281k53518849




            281k53518849











            • Had to read this thrice before my brain decided to stop editing out the repeated 'loop' at the start
              – Three Diag
              Jan 16 at 12:04
















            • Had to read this thrice before my brain decided to stop editing out the repeated 'loop' at the start
              – Three Diag
              Jan 16 at 12:04















            Had to read this thrice before my brain decided to stop editing out the repeated 'loop' at the start
            – Three Diag
            Jan 16 at 12:04




            Had to read this thrice before my brain decided to stop editing out the repeated 'loop' at the start
            – Three Diag
            Jan 16 at 12:04












            up vote
            21
            down vote













            This is the default behavior, yes. It is documented in the help of the for keyword:



            terdon@tpad ~ $ help for
            for: for NAME [in WORDS ... ] ; do COMMANDS; done
            Execute commands for each member in a list.

            The `for' loop executes a sequence of commands for each member in a
            list of items. If `in WORDS ...;' is not present, then `in "$@"' is
            assumed. For each element in WORDS, NAME is set to that element, and
            the COMMANDS are executed.

            Exit Status:
            Returns the status of the last command executed.


            So, when you don't give it a list to iterate over, it will default to iterating over $@, the array of positional parameters (a, b and c in your example).



            And this behavior is defined by POSIX so yes, it is considered "good practice" as far as that goes.






            share|improve this answer
























              up vote
              21
              down vote













              This is the default behavior, yes. It is documented in the help of the for keyword:



              terdon@tpad ~ $ help for
              for: for NAME [in WORDS ... ] ; do COMMANDS; done
              Execute commands for each member in a list.

              The `for' loop executes a sequence of commands for each member in a
              list of items. If `in WORDS ...;' is not present, then `in "$@"' is
              assumed. For each element in WORDS, NAME is set to that element, and
              the COMMANDS are executed.

              Exit Status:
              Returns the status of the last command executed.


              So, when you don't give it a list to iterate over, it will default to iterating over $@, the array of positional parameters (a, b and c in your example).



              And this behavior is defined by POSIX so yes, it is considered "good practice" as far as that goes.






              share|improve this answer






















                up vote
                21
                down vote










                up vote
                21
                down vote









                This is the default behavior, yes. It is documented in the help of the for keyword:



                terdon@tpad ~ $ help for
                for: for NAME [in WORDS ... ] ; do COMMANDS; done
                Execute commands for each member in a list.

                The `for' loop executes a sequence of commands for each member in a
                list of items. If `in WORDS ...;' is not present, then `in "$@"' is
                assumed. For each element in WORDS, NAME is set to that element, and
                the COMMANDS are executed.

                Exit Status:
                Returns the status of the last command executed.


                So, when you don't give it a list to iterate over, it will default to iterating over $@, the array of positional parameters (a, b and c in your example).



                And this behavior is defined by POSIX so yes, it is considered "good practice" as far as that goes.






                share|improve this answer












                This is the default behavior, yes. It is documented in the help of the for keyword:



                terdon@tpad ~ $ help for
                for: for NAME [in WORDS ... ] ; do COMMANDS; done
                Execute commands for each member in a list.

                The `for' loop executes a sequence of commands for each member in a
                list of items. If `in WORDS ...;' is not present, then `in "$@"' is
                assumed. For each element in WORDS, NAME is set to that element, and
                the COMMANDS are executed.

                Exit Status:
                Returns the status of the last command executed.


                So, when you don't give it a list to iterate over, it will default to iterating over $@, the array of positional parameters (a, b and c in your example).



                And this behavior is defined by POSIX so yes, it is considered "good practice" as far as that goes.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 15 at 16:59









                terdon♦

                122k28230403




                122k28230403






















                     

                    draft saved


                    draft discarded


























                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f417292%2fbash-for-loop-without-a-in-foo-bar-part%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    Peggy Mitchell

                    Palaiologos

                    The Forum (Inglewood, California)