Here documents as multiple lines command within the bash

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











up vote
1
down vote

favorite












I created a snippet to test the here document



$ cat test101.sh
ls
$ bash test101.sh
bmdt.md brmdh.md fild.md test test101.sh test2 test5 testfile
breakfast.md exec file.md test.sh test12 test3 test7


It come to Here document



$ $(cat << EOF
→ ls
→ EOF)
bmdt.md brmdh.md fild.md test test101.sh test2 test5 testfile
breakfast.md exec file.md test.sh test12 test3 test7


It works properly,

Unfortunately, it's not the case of structured command



$ $(cat << EOF
→ for i in *
→ do
→ stat $i
→ done
→ EOF)
-bash: for: command not found


I tried alternatively



$ bash $(cat << EOF
→ for i in *
→ do
→ stat $i
→ done
→ EOF)
bash: for: No such file or directory


What's the problem not allow the for command working?










share|improve this question







New contributor




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



















  • What are you trying to accomplish by using loop inside heredoc?
    – user1700494
    2 hours ago










  • learning to get a better understanding about how heredoc work. @user1700494
    – avirate
    2 hours ago











  • You'd need to escape the special characters, e.g. * -> *, $i -> $i
    – steve
    2 hours ago






  • 1




    @steve The * does not need special treatment as the shell won't do filename globbing on the contents of the document, only expansions.
    – Kusalananda
    2 hours ago














up vote
1
down vote

favorite












I created a snippet to test the here document



$ cat test101.sh
ls
$ bash test101.sh
bmdt.md brmdh.md fild.md test test101.sh test2 test5 testfile
breakfast.md exec file.md test.sh test12 test3 test7


It come to Here document



$ $(cat << EOF
→ ls
→ EOF)
bmdt.md brmdh.md fild.md test test101.sh test2 test5 testfile
breakfast.md exec file.md test.sh test12 test3 test7


It works properly,

Unfortunately, it's not the case of structured command



$ $(cat << EOF
→ for i in *
→ do
→ stat $i
→ done
→ EOF)
-bash: for: command not found


I tried alternatively



$ bash $(cat << EOF
→ for i in *
→ do
→ stat $i
→ done
→ EOF)
bash: for: No such file or directory


What's the problem not allow the for command working?










share|improve this question







New contributor




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



















  • What are you trying to accomplish by using loop inside heredoc?
    – user1700494
    2 hours ago










  • learning to get a better understanding about how heredoc work. @user1700494
    – avirate
    2 hours ago











  • You'd need to escape the special characters, e.g. * -> *, $i -> $i
    – steve
    2 hours ago






  • 1




    @steve The * does not need special treatment as the shell won't do filename globbing on the contents of the document, only expansions.
    – Kusalananda
    2 hours ago












up vote
1
down vote

favorite









up vote
1
down vote

favorite











I created a snippet to test the here document



$ cat test101.sh
ls
$ bash test101.sh
bmdt.md brmdh.md fild.md test test101.sh test2 test5 testfile
breakfast.md exec file.md test.sh test12 test3 test7


It come to Here document



$ $(cat << EOF
→ ls
→ EOF)
bmdt.md brmdh.md fild.md test test101.sh test2 test5 testfile
breakfast.md exec file.md test.sh test12 test3 test7


It works properly,

Unfortunately, it's not the case of structured command



$ $(cat << EOF
→ for i in *
→ do
→ stat $i
→ done
→ EOF)
-bash: for: command not found


I tried alternatively



$ bash $(cat << EOF
→ for i in *
→ do
→ stat $i
→ done
→ EOF)
bash: for: No such file or directory


What's the problem not allow the for command working?










share|improve this question







New contributor




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











I created a snippet to test the here document



$ cat test101.sh
ls
$ bash test101.sh
bmdt.md brmdh.md fild.md test test101.sh test2 test5 testfile
breakfast.md exec file.md test.sh test12 test3 test7


It come to Here document



$ $(cat << EOF
→ ls
→ EOF)
bmdt.md brmdh.md fild.md test test101.sh test2 test5 testfile
breakfast.md exec file.md test.sh test12 test3 test7


It works properly,

Unfortunately, it's not the case of structured command



$ $(cat << EOF
→ for i in *
→ do
→ stat $i
→ done
→ EOF)
-bash: for: command not found


I tried alternatively



$ bash $(cat << EOF
→ for i in *
→ do
→ stat $i
→ done
→ EOF)
bash: for: No such file or directory


What's the problem not allow the for command working?







bash






share|improve this question







New contributor




avirate 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




avirate 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






New contributor




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









asked 3 hours ago









avirate

41829




41829




New contributor




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





New contributor





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






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











  • What are you trying to accomplish by using loop inside heredoc?
    – user1700494
    2 hours ago










  • learning to get a better understanding about how heredoc work. @user1700494
    – avirate
    2 hours ago











  • You'd need to escape the special characters, e.g. * -> *, $i -> $i
    – steve
    2 hours ago






  • 1




    @steve The * does not need special treatment as the shell won't do filename globbing on the contents of the document, only expansions.
    – Kusalananda
    2 hours ago
















  • What are you trying to accomplish by using loop inside heredoc?
    – user1700494
    2 hours ago










  • learning to get a better understanding about how heredoc work. @user1700494
    – avirate
    2 hours ago











  • You'd need to escape the special characters, e.g. * -> *, $i -> $i
    – steve
    2 hours ago






  • 1




    @steve The * does not need special treatment as the shell won't do filename globbing on the contents of the document, only expansions.
    – Kusalananda
    2 hours ago















What are you trying to accomplish by using loop inside heredoc?
– user1700494
2 hours ago




What are you trying to accomplish by using loop inside heredoc?
– user1700494
2 hours ago












learning to get a better understanding about how heredoc work. @user1700494
– avirate
2 hours ago





learning to get a better understanding about how heredoc work. @user1700494
– avirate
2 hours ago













You'd need to escape the special characters, e.g. * -> *, $i -> $i
– steve
2 hours ago




You'd need to escape the special characters, e.g. * -> *, $i -> $i
– steve
2 hours ago




1




1




@steve The * does not need special treatment as the shell won't do filename globbing on the contents of the document, only expansions.
– Kusalananda
2 hours ago




@steve The * does not need special treatment as the shell won't do filename globbing on the contents of the document, only expansions.
– Kusalananda
2 hours ago










1 Answer
1






active

oldest

votes

















up vote
3
down vote



accepted










A here-document is a form of redirection. In your commands, you redirect into the cat command, and then try to use the output as a command in a command substitution.




  1. $i will be expanded when the contents of the here-document is formed. This happens long before the loop in the document actually runs. If the i variable is unset, it will expand to an empty string. You may choose to quote the here-document (by quoting the first EOF as 'EOF' or EOF) so that no expansions are done in it, or to explicitly escape the $ as $ to protect it from expansion.

  2. The contents of the here-document will be interpreted as a single string with new-line delimited lines. It will not undergo the usual token recognition and other steps involved in the parsing of ordinary commands, but will be split up into individual words since the command substitution is unquoted. In particular, for will not be recognised as a shell keyword. This is why your first failing example fails. To re-evaluate the string, you would have to eval it, which would re-evaluate the string as the shell would have done had it been given on the command line.

  3. The last example would expand to bash followed by a number of words. The first word is for, so bash would expect to run a shell script called for in the current directory, but fails in doing so.



  4. In all examples, bash should also have complained that the here-document was not properly terminated (since the last line is EOF) with a trailing right parenthesis, not EOF), saying something like



    bash: warning: here-document at line 1 delimited by end-of-file (wanted `EOF')


    unless you are using an older bash release, like the default one on macOS.



Instead, this would be a better choice of actions as it avoids converting code into a string that needs to be re-interpreted and instead gives the document as a in-line shell script directly to a shell interpreter to execute.



bash <<'END_SCRIPT'
for i in *; do
printf 'Filename: "%s"n' "$i"
done
END_SCRIPT


The first of your examples work because it's a simple command.






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
    );



    );






    avirate 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%2f478261%2fhere-documents-as-multiple-lines-command-within-the-bash%23new-answer', 'question_page');

    );

    Post as a guest






























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    3
    down vote



    accepted










    A here-document is a form of redirection. In your commands, you redirect into the cat command, and then try to use the output as a command in a command substitution.




    1. $i will be expanded when the contents of the here-document is formed. This happens long before the loop in the document actually runs. If the i variable is unset, it will expand to an empty string. You may choose to quote the here-document (by quoting the first EOF as 'EOF' or EOF) so that no expansions are done in it, or to explicitly escape the $ as $ to protect it from expansion.

    2. The contents of the here-document will be interpreted as a single string with new-line delimited lines. It will not undergo the usual token recognition and other steps involved in the parsing of ordinary commands, but will be split up into individual words since the command substitution is unquoted. In particular, for will not be recognised as a shell keyword. This is why your first failing example fails. To re-evaluate the string, you would have to eval it, which would re-evaluate the string as the shell would have done had it been given on the command line.

    3. The last example would expand to bash followed by a number of words. The first word is for, so bash would expect to run a shell script called for in the current directory, but fails in doing so.



    4. In all examples, bash should also have complained that the here-document was not properly terminated (since the last line is EOF) with a trailing right parenthesis, not EOF), saying something like



      bash: warning: here-document at line 1 delimited by end-of-file (wanted `EOF')


      unless you are using an older bash release, like the default one on macOS.



    Instead, this would be a better choice of actions as it avoids converting code into a string that needs to be re-interpreted and instead gives the document as a in-line shell script directly to a shell interpreter to execute.



    bash <<'END_SCRIPT'
    for i in *; do
    printf 'Filename: "%s"n' "$i"
    done
    END_SCRIPT


    The first of your examples work because it's a simple command.






    share|improve this answer


























      up vote
      3
      down vote



      accepted










      A here-document is a form of redirection. In your commands, you redirect into the cat command, and then try to use the output as a command in a command substitution.




      1. $i will be expanded when the contents of the here-document is formed. This happens long before the loop in the document actually runs. If the i variable is unset, it will expand to an empty string. You may choose to quote the here-document (by quoting the first EOF as 'EOF' or EOF) so that no expansions are done in it, or to explicitly escape the $ as $ to protect it from expansion.

      2. The contents of the here-document will be interpreted as a single string with new-line delimited lines. It will not undergo the usual token recognition and other steps involved in the parsing of ordinary commands, but will be split up into individual words since the command substitution is unquoted. In particular, for will not be recognised as a shell keyword. This is why your first failing example fails. To re-evaluate the string, you would have to eval it, which would re-evaluate the string as the shell would have done had it been given on the command line.

      3. The last example would expand to bash followed by a number of words. The first word is for, so bash would expect to run a shell script called for in the current directory, but fails in doing so.



      4. In all examples, bash should also have complained that the here-document was not properly terminated (since the last line is EOF) with a trailing right parenthesis, not EOF), saying something like



        bash: warning: here-document at line 1 delimited by end-of-file (wanted `EOF')


        unless you are using an older bash release, like the default one on macOS.



      Instead, this would be a better choice of actions as it avoids converting code into a string that needs to be re-interpreted and instead gives the document as a in-line shell script directly to a shell interpreter to execute.



      bash <<'END_SCRIPT'
      for i in *; do
      printf 'Filename: "%s"n' "$i"
      done
      END_SCRIPT


      The first of your examples work because it's a simple command.






      share|improve this answer
























        up vote
        3
        down vote



        accepted







        up vote
        3
        down vote



        accepted






        A here-document is a form of redirection. In your commands, you redirect into the cat command, and then try to use the output as a command in a command substitution.




        1. $i will be expanded when the contents of the here-document is formed. This happens long before the loop in the document actually runs. If the i variable is unset, it will expand to an empty string. You may choose to quote the here-document (by quoting the first EOF as 'EOF' or EOF) so that no expansions are done in it, or to explicitly escape the $ as $ to protect it from expansion.

        2. The contents of the here-document will be interpreted as a single string with new-line delimited lines. It will not undergo the usual token recognition and other steps involved in the parsing of ordinary commands, but will be split up into individual words since the command substitution is unquoted. In particular, for will not be recognised as a shell keyword. This is why your first failing example fails. To re-evaluate the string, you would have to eval it, which would re-evaluate the string as the shell would have done had it been given on the command line.

        3. The last example would expand to bash followed by a number of words. The first word is for, so bash would expect to run a shell script called for in the current directory, but fails in doing so.



        4. In all examples, bash should also have complained that the here-document was not properly terminated (since the last line is EOF) with a trailing right parenthesis, not EOF), saying something like



          bash: warning: here-document at line 1 delimited by end-of-file (wanted `EOF')


          unless you are using an older bash release, like the default one on macOS.



        Instead, this would be a better choice of actions as it avoids converting code into a string that needs to be re-interpreted and instead gives the document as a in-line shell script directly to a shell interpreter to execute.



        bash <<'END_SCRIPT'
        for i in *; do
        printf 'Filename: "%s"n' "$i"
        done
        END_SCRIPT


        The first of your examples work because it's a simple command.






        share|improve this answer














        A here-document is a form of redirection. In your commands, you redirect into the cat command, and then try to use the output as a command in a command substitution.




        1. $i will be expanded when the contents of the here-document is formed. This happens long before the loop in the document actually runs. If the i variable is unset, it will expand to an empty string. You may choose to quote the here-document (by quoting the first EOF as 'EOF' or EOF) so that no expansions are done in it, or to explicitly escape the $ as $ to protect it from expansion.

        2. The contents of the here-document will be interpreted as a single string with new-line delimited lines. It will not undergo the usual token recognition and other steps involved in the parsing of ordinary commands, but will be split up into individual words since the command substitution is unquoted. In particular, for will not be recognised as a shell keyword. This is why your first failing example fails. To re-evaluate the string, you would have to eval it, which would re-evaluate the string as the shell would have done had it been given on the command line.

        3. The last example would expand to bash followed by a number of words. The first word is for, so bash would expect to run a shell script called for in the current directory, but fails in doing so.



        4. In all examples, bash should also have complained that the here-document was not properly terminated (since the last line is EOF) with a trailing right parenthesis, not EOF), saying something like



          bash: warning: here-document at line 1 delimited by end-of-file (wanted `EOF')


          unless you are using an older bash release, like the default one on macOS.



        Instead, this would be a better choice of actions as it avoids converting code into a string that needs to be re-interpreted and instead gives the document as a in-line shell script directly to a shell interpreter to execute.



        bash <<'END_SCRIPT'
        for i in *; do
        printf 'Filename: "%s"n' "$i"
        done
        END_SCRIPT


        The first of your examples work because it's a simple command.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 1 hour ago

























        answered 2 hours ago









        Kusalananda

        112k15216343




        112k15216343




















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









             

            draft saved


            draft discarded


















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












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











            avirate 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%2f478261%2fhere-documents-as-multiple-lines-command-within-the-bash%23new-answer', 'question_page');

            );

            Post as a guest













































































            Comments

            Popular posts from this blog

            What does second last employer means? [closed]

            Installing NextGIS Connect into QGIS 3?

            One-line joke