b2 command finds ICU when called directly but not from indirect bash script variable









up vote
2
down vote

favorite












I have this strange issue with my bash script. I compile boost as part of it. The call from the script looks like this:



./b2 --reconfigure $PARALLEL link=static cxxflags=-fPIC install boost.locale.iconv=off boost.locale.posix=off -sICU_PATH="$ICU_PREFIX" -sICU_LINK="$BOOST_ICU_LIBS" >> "$BOOST_LOG" 2>&1


That command works perfectly well. The log file shows that it finds ICU without a problem. However, if I change it to run from a variable, it no longer finds ICU (but it still compiles everything else):



bcmd="./b2 --reconfigure $PARALLEL link=static cxxflags=-fPIC install boost.locale.iconv=off boost.locale.posix=off -sICU_PATH="$ICU_PREFIX" -sICU_LINK="$BOOST_ICU_LIBS""
$bcmd >> "$BOOST_LOG" 2>&1


What's the difference? I would like to be able to use the second approach so that I can pass the command into another function before running it.










share|improve this question















This question has an open bounty worth +50
reputation from Brannon ending ending at 2018-11-25 21:28:54Z">in 4 days.


This question has not received enough attention.



















    up vote
    2
    down vote

    favorite












    I have this strange issue with my bash script. I compile boost as part of it. The call from the script looks like this:



    ./b2 --reconfigure $PARALLEL link=static cxxflags=-fPIC install boost.locale.iconv=off boost.locale.posix=off -sICU_PATH="$ICU_PREFIX" -sICU_LINK="$BOOST_ICU_LIBS" >> "$BOOST_LOG" 2>&1


    That command works perfectly well. The log file shows that it finds ICU without a problem. However, if I change it to run from a variable, it no longer finds ICU (but it still compiles everything else):



    bcmd="./b2 --reconfigure $PARALLEL link=static cxxflags=-fPIC install boost.locale.iconv=off boost.locale.posix=off -sICU_PATH="$ICU_PREFIX" -sICU_LINK="$BOOST_ICU_LIBS""
    $bcmd >> "$BOOST_LOG" 2>&1


    What's the difference? I would like to be able to use the second approach so that I can pass the command into another function before running it.










    share|improve this question















    This question has an open bounty worth +50
    reputation from Brannon ending ending at 2018-11-25 21:28:54Z">in 4 days.


    This question has not received enough attention.

















      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      I have this strange issue with my bash script. I compile boost as part of it. The call from the script looks like this:



      ./b2 --reconfigure $PARALLEL link=static cxxflags=-fPIC install boost.locale.iconv=off boost.locale.posix=off -sICU_PATH="$ICU_PREFIX" -sICU_LINK="$BOOST_ICU_LIBS" >> "$BOOST_LOG" 2>&1


      That command works perfectly well. The log file shows that it finds ICU without a problem. However, if I change it to run from a variable, it no longer finds ICU (but it still compiles everything else):



      bcmd="./b2 --reconfigure $PARALLEL link=static cxxflags=-fPIC install boost.locale.iconv=off boost.locale.posix=off -sICU_PATH="$ICU_PREFIX" -sICU_LINK="$BOOST_ICU_LIBS""
      $bcmd >> "$BOOST_LOG" 2>&1


      What's the difference? I would like to be able to use the second approach so that I can pass the command into another function before running it.










      share|improve this question













      I have this strange issue with my bash script. I compile boost as part of it. The call from the script looks like this:



      ./b2 --reconfigure $PARALLEL link=static cxxflags=-fPIC install boost.locale.iconv=off boost.locale.posix=off -sICU_PATH="$ICU_PREFIX" -sICU_LINK="$BOOST_ICU_LIBS" >> "$BOOST_LOG" 2>&1


      That command works perfectly well. The log file shows that it finds ICU without a problem. However, if I change it to run from a variable, it no longer finds ICU (but it still compiles everything else):



      bcmd="./b2 --reconfigure $PARALLEL link=static cxxflags=-fPIC install boost.locale.iconv=off boost.locale.posix=off -sICU_PATH="$ICU_PREFIX" -sICU_LINK="$BOOST_ICU_LIBS""
      $bcmd >> "$BOOST_LOG" 2>&1


      What's the difference? I would like to be able to use the second approach so that I can pass the command into another function before running it.







      bash boost compilation






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 8 at 19:04









      Brannon

      2,99212161




      2,99212161






      This question has an open bounty worth +50
      reputation from Brannon ending ending at 2018-11-25 21:28:54Z">in 4 days.


      This question has not received enough attention.








      This question has an open bounty worth +50
      reputation from Brannon ending ending at 2018-11-25 21:28:54Z">in 4 days.


      This question has not received enough attention.
























          2 Answers
          2






          active

          oldest

          votes

















          up vote
          0
          down vote













          Try to use eval when you want to execute a string as a command. This way, you won't have issues regarding strings that have spaces etc. The expanded cmd string is not re-evaluated by bash hence, things like "hi there" are expanded as two separate tokens.



          eval $bcmd >> "$BOOST_LOG" 2>&1


          To demonstrate this behavior, consider this code:



          cmd='echo "hi there"'
          $cmd
          eval $cmd


          Which outputs to:



          "hi there"
          hi there


          The token "hi there" is not re-evaluated as a quoted string.






          share|improve this answer





























            up vote
            0
            down vote













            Don't use a variable to store complex commands involving quotes that are nested. The problem is when you call the variable with just $cmd, the quotes are stripped incorrectly. Putting commands (or parts of commands) into variables and then getting them back out intact is complicated.



            Quote removal is part of the one of the word expansions done by the shell. From the excerpt seen in POSIX specification of shell




            2.6.7 Quote Removal



            The quote characters ( backslash, single-quote, and double-quote) that were present in the original word shall be removed unless they have themselves been quoted.




            Your example can be simply reproduced by a simple example. Assuming you have a few command flags (not actual ones)



            cmdFlags='--archive --exclude="foo bar.txt"'


            If you carefully look through the above, it contains 2 args, one --archive and another for --exclude="foo bar.txt", notice the double-quotes which needs to be preserved when you are passing it.



            Notice how the quotes are incorrectly split when I don't quote cmdFlags, in the printf() call below



            printf "'%s' " $cmdFlags; printf 'n'
            '--archive' '--exclude="foo' 'bar.txt"'


            and compare the result with one with proper quoting done below.



            printf "'%s' " "$cmdFlags"; printf 'n'
            '--archive --exclude="foo bar.txt"'


            So along with the suggestion of properly quoting the variable, the general suggestion would be to use an array to store the flags and pass the quoted array expansion



            cmdArray=()
            cmdArray=(./b2 --reconfigure $PARALLEL link=static cxxflags=-fPIC install boost.locale.iconv=off boost.locale.posix=off -sICU_PATH="$ICU_PREFIX" -sICU_LINK="$BOOST_ICU_LIBS")


            and pass the array as



            "$cmdArrray[@]" >> "$BOOST_LOG" 2>&1





            share|improve this answer




















              Your Answer






              StackExchange.ifUsing("editor", function ()
              StackExchange.using("externalEditor", function ()
              StackExchange.using("snippets", function ()
              StackExchange.snippets.init();
              );
              );
              , "code-snippets");

              StackExchange.ready(function()
              var channelOptions =
              tags: "".split(" "),
              id: "1"
              ;
              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: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader:
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              ,
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              );



              );













               

              draft saved


              draft discarded


















              StackExchange.ready(
              function ()
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53214510%2fb2-command-finds-icu-when-called-directly-but-not-from-indirect-bash-script-vari%23new-answer', 'question_page');

              );

              Post as a guest















              Required, but never shown

























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              0
              down vote













              Try to use eval when you want to execute a string as a command. This way, you won't have issues regarding strings that have spaces etc. The expanded cmd string is not re-evaluated by bash hence, things like "hi there" are expanded as two separate tokens.



              eval $bcmd >> "$BOOST_LOG" 2>&1


              To demonstrate this behavior, consider this code:



              cmd='echo "hi there"'
              $cmd
              eval $cmd


              Which outputs to:



              "hi there"
              hi there


              The token "hi there" is not re-evaluated as a quoted string.






              share|improve this answer


























                up vote
                0
                down vote













                Try to use eval when you want to execute a string as a command. This way, you won't have issues regarding strings that have spaces etc. The expanded cmd string is not re-evaluated by bash hence, things like "hi there" are expanded as two separate tokens.



                eval $bcmd >> "$BOOST_LOG" 2>&1


                To demonstrate this behavior, consider this code:



                cmd='echo "hi there"'
                $cmd
                eval $cmd


                Which outputs to:



                "hi there"
                hi there


                The token "hi there" is not re-evaluated as a quoted string.






                share|improve this answer
























                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  Try to use eval when you want to execute a string as a command. This way, you won't have issues regarding strings that have spaces etc. The expanded cmd string is not re-evaluated by bash hence, things like "hi there" are expanded as two separate tokens.



                  eval $bcmd >> "$BOOST_LOG" 2>&1


                  To demonstrate this behavior, consider this code:



                  cmd='echo "hi there"'
                  $cmd
                  eval $cmd


                  Which outputs to:



                  "hi there"
                  hi there


                  The token "hi there" is not re-evaluated as a quoted string.






                  share|improve this answer














                  Try to use eval when you want to execute a string as a command. This way, you won't have issues regarding strings that have spaces etc. The expanded cmd string is not re-evaluated by bash hence, things like "hi there" are expanded as two separate tokens.



                  eval $bcmd >> "$BOOST_LOG" 2>&1


                  To demonstrate this behavior, consider this code:



                  cmd='echo "hi there"'
                  $cmd
                  eval $cmd


                  Which outputs to:



                  "hi there"
                  hi there


                  The token "hi there" is not re-evaluated as a quoted string.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 2 days ago

























                  answered 2 days ago









                  ssemilla

                  2,197419




                  2,197419






















                      up vote
                      0
                      down vote













                      Don't use a variable to store complex commands involving quotes that are nested. The problem is when you call the variable with just $cmd, the quotes are stripped incorrectly. Putting commands (or parts of commands) into variables and then getting them back out intact is complicated.



                      Quote removal is part of the one of the word expansions done by the shell. From the excerpt seen in POSIX specification of shell




                      2.6.7 Quote Removal



                      The quote characters ( backslash, single-quote, and double-quote) that were present in the original word shall be removed unless they have themselves been quoted.




                      Your example can be simply reproduced by a simple example. Assuming you have a few command flags (not actual ones)



                      cmdFlags='--archive --exclude="foo bar.txt"'


                      If you carefully look through the above, it contains 2 args, one --archive and another for --exclude="foo bar.txt", notice the double-quotes which needs to be preserved when you are passing it.



                      Notice how the quotes are incorrectly split when I don't quote cmdFlags, in the printf() call below



                      printf "'%s' " $cmdFlags; printf 'n'
                      '--archive' '--exclude="foo' 'bar.txt"'


                      and compare the result with one with proper quoting done below.



                      printf "'%s' " "$cmdFlags"; printf 'n'
                      '--archive --exclude="foo bar.txt"'


                      So along with the suggestion of properly quoting the variable, the general suggestion would be to use an array to store the flags and pass the quoted array expansion



                      cmdArray=()
                      cmdArray=(./b2 --reconfigure $PARALLEL link=static cxxflags=-fPIC install boost.locale.iconv=off boost.locale.posix=off -sICU_PATH="$ICU_PREFIX" -sICU_LINK="$BOOST_ICU_LIBS")


                      and pass the array as



                      "$cmdArrray[@]" >> "$BOOST_LOG" 2>&1





                      share|improve this answer
























                        up vote
                        0
                        down vote













                        Don't use a variable to store complex commands involving quotes that are nested. The problem is when you call the variable with just $cmd, the quotes are stripped incorrectly. Putting commands (or parts of commands) into variables and then getting them back out intact is complicated.



                        Quote removal is part of the one of the word expansions done by the shell. From the excerpt seen in POSIX specification of shell




                        2.6.7 Quote Removal



                        The quote characters ( backslash, single-quote, and double-quote) that were present in the original word shall be removed unless they have themselves been quoted.




                        Your example can be simply reproduced by a simple example. Assuming you have a few command flags (not actual ones)



                        cmdFlags='--archive --exclude="foo bar.txt"'


                        If you carefully look through the above, it contains 2 args, one --archive and another for --exclude="foo bar.txt", notice the double-quotes which needs to be preserved when you are passing it.



                        Notice how the quotes are incorrectly split when I don't quote cmdFlags, in the printf() call below



                        printf "'%s' " $cmdFlags; printf 'n'
                        '--archive' '--exclude="foo' 'bar.txt"'


                        and compare the result with one with proper quoting done below.



                        printf "'%s' " "$cmdFlags"; printf 'n'
                        '--archive --exclude="foo bar.txt"'


                        So along with the suggestion of properly quoting the variable, the general suggestion would be to use an array to store the flags and pass the quoted array expansion



                        cmdArray=()
                        cmdArray=(./b2 --reconfigure $PARALLEL link=static cxxflags=-fPIC install boost.locale.iconv=off boost.locale.posix=off -sICU_PATH="$ICU_PREFIX" -sICU_LINK="$BOOST_ICU_LIBS")


                        and pass the array as



                        "$cmdArrray[@]" >> "$BOOST_LOG" 2>&1





                        share|improve this answer






















                          up vote
                          0
                          down vote










                          up vote
                          0
                          down vote









                          Don't use a variable to store complex commands involving quotes that are nested. The problem is when you call the variable with just $cmd, the quotes are stripped incorrectly. Putting commands (or parts of commands) into variables and then getting them back out intact is complicated.



                          Quote removal is part of the one of the word expansions done by the shell. From the excerpt seen in POSIX specification of shell




                          2.6.7 Quote Removal



                          The quote characters ( backslash, single-quote, and double-quote) that were present in the original word shall be removed unless they have themselves been quoted.




                          Your example can be simply reproduced by a simple example. Assuming you have a few command flags (not actual ones)



                          cmdFlags='--archive --exclude="foo bar.txt"'


                          If you carefully look through the above, it contains 2 args, one --archive and another for --exclude="foo bar.txt", notice the double-quotes which needs to be preserved when you are passing it.



                          Notice how the quotes are incorrectly split when I don't quote cmdFlags, in the printf() call below



                          printf "'%s' " $cmdFlags; printf 'n'
                          '--archive' '--exclude="foo' 'bar.txt"'


                          and compare the result with one with proper quoting done below.



                          printf "'%s' " "$cmdFlags"; printf 'n'
                          '--archive --exclude="foo bar.txt"'


                          So along with the suggestion of properly quoting the variable, the general suggestion would be to use an array to store the flags and pass the quoted array expansion



                          cmdArray=()
                          cmdArray=(./b2 --reconfigure $PARALLEL link=static cxxflags=-fPIC install boost.locale.iconv=off boost.locale.posix=off -sICU_PATH="$ICU_PREFIX" -sICU_LINK="$BOOST_ICU_LIBS")


                          and pass the array as



                          "$cmdArrray[@]" >> "$BOOST_LOG" 2>&1





                          share|improve this answer












                          Don't use a variable to store complex commands involving quotes that are nested. The problem is when you call the variable with just $cmd, the quotes are stripped incorrectly. Putting commands (or parts of commands) into variables and then getting them back out intact is complicated.



                          Quote removal is part of the one of the word expansions done by the shell. From the excerpt seen in POSIX specification of shell




                          2.6.7 Quote Removal



                          The quote characters ( backslash, single-quote, and double-quote) that were present in the original word shall be removed unless they have themselves been quoted.




                          Your example can be simply reproduced by a simple example. Assuming you have a few command flags (not actual ones)



                          cmdFlags='--archive --exclude="foo bar.txt"'


                          If you carefully look through the above, it contains 2 args, one --archive and another for --exclude="foo bar.txt", notice the double-quotes which needs to be preserved when you are passing it.



                          Notice how the quotes are incorrectly split when I don't quote cmdFlags, in the printf() call below



                          printf "'%s' " $cmdFlags; printf 'n'
                          '--archive' '--exclude="foo' 'bar.txt"'


                          and compare the result with one with proper quoting done below.



                          printf "'%s' " "$cmdFlags"; printf 'n'
                          '--archive --exclude="foo bar.txt"'


                          So along with the suggestion of properly quoting the variable, the general suggestion would be to use an array to store the flags and pass the quoted array expansion



                          cmdArray=()
                          cmdArray=(./b2 --reconfigure $PARALLEL link=static cxxflags=-fPIC install boost.locale.iconv=off boost.locale.posix=off -sICU_PATH="$ICU_PREFIX" -sICU_LINK="$BOOST_ICU_LIBS")


                          and pass the array as



                          "$cmdArrray[@]" >> "$BOOST_LOG" 2>&1






                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered 20 hours ago









                          Inian

                          37.3k63668




                          37.3k63668



























                               

                              draft saved


                              draft discarded















































                               


                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function ()
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53214510%2fb2-command-finds-icu-when-called-directly-but-not-from-indirect-bash-script-vari%23new-answer', 'question_page');

                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

                              Edmonton

                              Crossroads (UK TV series)