How can I generate arguments to another command via command substitution












7















Following on from:
unexpected behaviour in shell command substitution



I have a command which can take a huge list of arguments, some of which can legitimately contain spaces (and probably other things)



I wrote a script which can generate those arguments for me, with quotes, but I must copy and paste the output e.g.



./somecommand
<output on stdout with quoting>
./othercommand some_args <output from above>


I tried to streamline this by simply doing



./othercommand $(./somecommand)


and ran into the unexpected behaviour mentioned in question above. The question is -- can command substitution be reliably used to generate the arguments to othercommand given that some arguments require quoting and this cannot be changed?










share|improve this question

























  • Depends on what you mean by "reliably". If you want next command take the output exactly as it appears on screen and apply shell rules to it, then maybe eval could be used, but it's generally not recommended. xargs is something to consider as well

    – Sergiy Kolodyazhnyy
    3 hours ago











  • I'd like (expect) the output from somecommand to undergo regular shell parsing

    – user1207217
    3 hours ago











  • As I said in my answer, use some other character for field splitting (like :)... assuming that character will reliably not be in the output.

    – Olorin
    3 hours ago













  • But that's not really right because it doesn't obey quoting rules, which is what this is about

    – user1207217
    3 hours ago






  • 2





    Could you post a real-world example? I mean, the actual output of the first command and how you want it to interact with the second command.

    – nxnev
    3 hours ago
















7















Following on from:
unexpected behaviour in shell command substitution



I have a command which can take a huge list of arguments, some of which can legitimately contain spaces (and probably other things)



I wrote a script which can generate those arguments for me, with quotes, but I must copy and paste the output e.g.



./somecommand
<output on stdout with quoting>
./othercommand some_args <output from above>


I tried to streamline this by simply doing



./othercommand $(./somecommand)


and ran into the unexpected behaviour mentioned in question above. The question is -- can command substitution be reliably used to generate the arguments to othercommand given that some arguments require quoting and this cannot be changed?










share|improve this question

























  • Depends on what you mean by "reliably". If you want next command take the output exactly as it appears on screen and apply shell rules to it, then maybe eval could be used, but it's generally not recommended. xargs is something to consider as well

    – Sergiy Kolodyazhnyy
    3 hours ago











  • I'd like (expect) the output from somecommand to undergo regular shell parsing

    – user1207217
    3 hours ago











  • As I said in my answer, use some other character for field splitting (like :)... assuming that character will reliably not be in the output.

    – Olorin
    3 hours ago













  • But that's not really right because it doesn't obey quoting rules, which is what this is about

    – user1207217
    3 hours ago






  • 2





    Could you post a real-world example? I mean, the actual output of the first command and how you want it to interact with the second command.

    – nxnev
    3 hours ago














7












7








7


2






Following on from:
unexpected behaviour in shell command substitution



I have a command which can take a huge list of arguments, some of which can legitimately contain spaces (and probably other things)



I wrote a script which can generate those arguments for me, with quotes, but I must copy and paste the output e.g.



./somecommand
<output on stdout with quoting>
./othercommand some_args <output from above>


I tried to streamline this by simply doing



./othercommand $(./somecommand)


and ran into the unexpected behaviour mentioned in question above. The question is -- can command substitution be reliably used to generate the arguments to othercommand given that some arguments require quoting and this cannot be changed?










share|improve this question
















Following on from:
unexpected behaviour in shell command substitution



I have a command which can take a huge list of arguments, some of which can legitimately contain spaces (and probably other things)



I wrote a script which can generate those arguments for me, with quotes, but I must copy and paste the output e.g.



./somecommand
<output on stdout with quoting>
./othercommand some_args <output from above>


I tried to streamline this by simply doing



./othercommand $(./somecommand)


and ran into the unexpected behaviour mentioned in question above. The question is -- can command substitution be reliably used to generate the arguments to othercommand given that some arguments require quoting and this cannot be changed?







shell






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 1 hour ago









Rui F Ribeiro

39.6k1479132




39.6k1479132










asked 3 hours ago









user1207217user1207217

58137




58137













  • Depends on what you mean by "reliably". If you want next command take the output exactly as it appears on screen and apply shell rules to it, then maybe eval could be used, but it's generally not recommended. xargs is something to consider as well

    – Sergiy Kolodyazhnyy
    3 hours ago











  • I'd like (expect) the output from somecommand to undergo regular shell parsing

    – user1207217
    3 hours ago











  • As I said in my answer, use some other character for field splitting (like :)... assuming that character will reliably not be in the output.

    – Olorin
    3 hours ago













  • But that's not really right because it doesn't obey quoting rules, which is what this is about

    – user1207217
    3 hours ago






  • 2





    Could you post a real-world example? I mean, the actual output of the first command and how you want it to interact with the second command.

    – nxnev
    3 hours ago



















  • Depends on what you mean by "reliably". If you want next command take the output exactly as it appears on screen and apply shell rules to it, then maybe eval could be used, but it's generally not recommended. xargs is something to consider as well

    – Sergiy Kolodyazhnyy
    3 hours ago











  • I'd like (expect) the output from somecommand to undergo regular shell parsing

    – user1207217
    3 hours ago











  • As I said in my answer, use some other character for field splitting (like :)... assuming that character will reliably not be in the output.

    – Olorin
    3 hours ago













  • But that's not really right because it doesn't obey quoting rules, which is what this is about

    – user1207217
    3 hours ago






  • 2





    Could you post a real-world example? I mean, the actual output of the first command and how you want it to interact with the second command.

    – nxnev
    3 hours ago

















Depends on what you mean by "reliably". If you want next command take the output exactly as it appears on screen and apply shell rules to it, then maybe eval could be used, but it's generally not recommended. xargs is something to consider as well

– Sergiy Kolodyazhnyy
3 hours ago





Depends on what you mean by "reliably". If you want next command take the output exactly as it appears on screen and apply shell rules to it, then maybe eval could be used, but it's generally not recommended. xargs is something to consider as well

– Sergiy Kolodyazhnyy
3 hours ago













I'd like (expect) the output from somecommand to undergo regular shell parsing

– user1207217
3 hours ago





I'd like (expect) the output from somecommand to undergo regular shell parsing

– user1207217
3 hours ago













As I said in my answer, use some other character for field splitting (like :)... assuming that character will reliably not be in the output.

– Olorin
3 hours ago







As I said in my answer, use some other character for field splitting (like :)... assuming that character will reliably not be in the output.

– Olorin
3 hours ago















But that's not really right because it doesn't obey quoting rules, which is what this is about

– user1207217
3 hours ago





But that's not really right because it doesn't obey quoting rules, which is what this is about

– user1207217
3 hours ago




2




2





Could you post a real-world example? I mean, the actual output of the first command and how you want it to interact with the second command.

– nxnev
3 hours ago





Could you post a real-world example? I mean, the actual output of the first command and how you want it to interact with the second command.

– nxnev
3 hours ago










3 Answers
3






active

oldest

votes


















8















I wrote a script which can generate those arguments for me, with quotes




If the output is properly quoted for the shell, and you trust the output, then you could run eval on it.



Assuming you have a shell that supports arrays, it would be best to use one to store the arguments you get.



If ./gen_args.sh produces output like 'foo bar' '*' asdf, then we could run eval "args=( $(./gen_args.sh) )" to populate an array called args with the results. That would be the three elements foo bar, *, asdf.



We can use "${args[@]}" as usual to expand the array elements individually:



$ eval "args=( $(./gen_args.sh) )"
$ for var in "${args[@]}"; do printf ":%s:n" "$var"; done
:foo bar:
:*:
:asdf:


However, eval will happily run any shell substitutions, so $HOME in the output would expand to your home directory, and a command substitution would actually run a command in the shell running eval. An output of "$(date >&2)" would create a single empty array element and print the current date on stdout. This is a concern if gen_args.sh gets the data from some untrusted source, like another host over the network, file names created by other users. The output could include arbitrary commands. (If get_args.sh itself was malicious, it wouldn't need to output anything, it could just run the malicious commands directly.)





An alternative to shell quoting, which is hard to parse without eval, would be to use some other character as separator in the output of your script. You'd need to pick one that is not needed in the actual arguments.



Let's choose #, and have the script output foo bar#*#asdf. Now we can use unquoted command expansion to split the output of the command to the arguments.



$ IFS='#'                          # split on '#' signs
$ set -f # disable globbing
$ args=( $( ./gen_args3.sh ) ) # assign the values to the array
$ for var in "${args[@]}"; do printf ":%s:n" "$var"; done
:foo bar:
:*:
:asdf:


You'll need to set IFS back later if you depend on word splitting elsewhere in the script (unset IFS should work to make it the default), and also use set +f if you want to use globbing later.



If you're not using Bash or some other shell that has arrays, you could use the positional parameters for that. Replace args=( $(...) ) with set -- $(./gen_args.sh) and use "$@" instead of "${args[@]}" then.






share|improve this answer


























  • Best of both worlds!

    – Olorin
    2 hours ago



















4














If the somecommand output is in reliably good shell syntax, you can use eval:



$ eval sh test.sh $(echo '"hello " "hi and bye"')
hello
hi and bye


But you have to be sure that the output has valid quoting and such, otherwise you might end up running commands outside the script as well:



$ cat test.sh 
for var in "$@"
do
echo "|$var|"
done
$ ls
bar baz test.sh
$ eval sh test.sh $(echo '"hello " "hi and bye"; echo rm *')
|hello |
|hi and bye|
rm bar baz test.sh


Note that echo rm bar baz test.sh wasn't passed to the script (because of the ;) and was run as a separate command. I added the | around $var to highlight this.





Generally, unless you can completely trust the output of somecommand, it's not possible to reliably use its output to build a command string.






share|improve this answer































    3














    The issue is that once your somecommand script outputs the options, it's really just text and at the mercy of the shell's standard parsing (affected by whatever $IFS happens to be and what shell options are in effect).



    Instead of using somecommand to output the options, it would be easier, safer, and more robust to use it to call othercommand.



    In bash, ksh or zsh, you could then easily use an array to hold the individual options inside somecommand like so:



    options=( "hi there" "nice weather" "here's a star" "*" )
    options+=( "bonus bumblebee!" ) # add additional option


    Then call othercommand (still within somecommand):



    othercommand "${options[@]}"


    The expansion of "${options[@]}" would ensure that each element of the options array is individually quoted and presented to othercommand as separate arguments.



    In /bin/sh, use $@ to hold the options:



    set -- "hi there" "nice weather" "here's a star" "*"
    set -- "$@" "bonus bumblebee!" # add additional option

    othercommand "$@"


    (set is the command used for setting the positional parameters $1, $2, $3 etc. These are what makes up the array $@ in a standard POSIX shell. The initial -- is to signal to set that there are no options given, only arguments. The -- is really only needed if the first value happens to be something starting with -).



    Note that it's the double quotes around $@ and ${options[@]} that ensures that the elements are not individually word-splitted (and filename globbed).






    share|improve this answer


























    • could you explain set -- ?

      – user1207217
      2 hours ago











    • @user1207217 Added explanation to answer.

      – Kusalananda
      2 hours ago











    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',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    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%2funix.stackexchange.com%2fquestions%2f495769%2fhow-can-i-generate-arguments-to-another-command-via-command-substitution%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    8















    I wrote a script which can generate those arguments for me, with quotes




    If the output is properly quoted for the shell, and you trust the output, then you could run eval on it.



    Assuming you have a shell that supports arrays, it would be best to use one to store the arguments you get.



    If ./gen_args.sh produces output like 'foo bar' '*' asdf, then we could run eval "args=( $(./gen_args.sh) )" to populate an array called args with the results. That would be the three elements foo bar, *, asdf.



    We can use "${args[@]}" as usual to expand the array elements individually:



    $ eval "args=( $(./gen_args.sh) )"
    $ for var in "${args[@]}"; do printf ":%s:n" "$var"; done
    :foo bar:
    :*:
    :asdf:


    However, eval will happily run any shell substitutions, so $HOME in the output would expand to your home directory, and a command substitution would actually run a command in the shell running eval. An output of "$(date >&2)" would create a single empty array element and print the current date on stdout. This is a concern if gen_args.sh gets the data from some untrusted source, like another host over the network, file names created by other users. The output could include arbitrary commands. (If get_args.sh itself was malicious, it wouldn't need to output anything, it could just run the malicious commands directly.)





    An alternative to shell quoting, which is hard to parse without eval, would be to use some other character as separator in the output of your script. You'd need to pick one that is not needed in the actual arguments.



    Let's choose #, and have the script output foo bar#*#asdf. Now we can use unquoted command expansion to split the output of the command to the arguments.



    $ IFS='#'                          # split on '#' signs
    $ set -f # disable globbing
    $ args=( $( ./gen_args3.sh ) ) # assign the values to the array
    $ for var in "${args[@]}"; do printf ":%s:n" "$var"; done
    :foo bar:
    :*:
    :asdf:


    You'll need to set IFS back later if you depend on word splitting elsewhere in the script (unset IFS should work to make it the default), and also use set +f if you want to use globbing later.



    If you're not using Bash or some other shell that has arrays, you could use the positional parameters for that. Replace args=( $(...) ) with set -- $(./gen_args.sh) and use "$@" instead of "${args[@]}" then.






    share|improve this answer


























    • Best of both worlds!

      – Olorin
      2 hours ago
















    8















    I wrote a script which can generate those arguments for me, with quotes




    If the output is properly quoted for the shell, and you trust the output, then you could run eval on it.



    Assuming you have a shell that supports arrays, it would be best to use one to store the arguments you get.



    If ./gen_args.sh produces output like 'foo bar' '*' asdf, then we could run eval "args=( $(./gen_args.sh) )" to populate an array called args with the results. That would be the three elements foo bar, *, asdf.



    We can use "${args[@]}" as usual to expand the array elements individually:



    $ eval "args=( $(./gen_args.sh) )"
    $ for var in "${args[@]}"; do printf ":%s:n" "$var"; done
    :foo bar:
    :*:
    :asdf:


    However, eval will happily run any shell substitutions, so $HOME in the output would expand to your home directory, and a command substitution would actually run a command in the shell running eval. An output of "$(date >&2)" would create a single empty array element and print the current date on stdout. This is a concern if gen_args.sh gets the data from some untrusted source, like another host over the network, file names created by other users. The output could include arbitrary commands. (If get_args.sh itself was malicious, it wouldn't need to output anything, it could just run the malicious commands directly.)





    An alternative to shell quoting, which is hard to parse without eval, would be to use some other character as separator in the output of your script. You'd need to pick one that is not needed in the actual arguments.



    Let's choose #, and have the script output foo bar#*#asdf. Now we can use unquoted command expansion to split the output of the command to the arguments.



    $ IFS='#'                          # split on '#' signs
    $ set -f # disable globbing
    $ args=( $( ./gen_args3.sh ) ) # assign the values to the array
    $ for var in "${args[@]}"; do printf ":%s:n" "$var"; done
    :foo bar:
    :*:
    :asdf:


    You'll need to set IFS back later if you depend on word splitting elsewhere in the script (unset IFS should work to make it the default), and also use set +f if you want to use globbing later.



    If you're not using Bash or some other shell that has arrays, you could use the positional parameters for that. Replace args=( $(...) ) with set -- $(./gen_args.sh) and use "$@" instead of "${args[@]}" then.






    share|improve this answer


























    • Best of both worlds!

      – Olorin
      2 hours ago














    8












    8








    8








    I wrote a script which can generate those arguments for me, with quotes




    If the output is properly quoted for the shell, and you trust the output, then you could run eval on it.



    Assuming you have a shell that supports arrays, it would be best to use one to store the arguments you get.



    If ./gen_args.sh produces output like 'foo bar' '*' asdf, then we could run eval "args=( $(./gen_args.sh) )" to populate an array called args with the results. That would be the three elements foo bar, *, asdf.



    We can use "${args[@]}" as usual to expand the array elements individually:



    $ eval "args=( $(./gen_args.sh) )"
    $ for var in "${args[@]}"; do printf ":%s:n" "$var"; done
    :foo bar:
    :*:
    :asdf:


    However, eval will happily run any shell substitutions, so $HOME in the output would expand to your home directory, and a command substitution would actually run a command in the shell running eval. An output of "$(date >&2)" would create a single empty array element and print the current date on stdout. This is a concern if gen_args.sh gets the data from some untrusted source, like another host over the network, file names created by other users. The output could include arbitrary commands. (If get_args.sh itself was malicious, it wouldn't need to output anything, it could just run the malicious commands directly.)





    An alternative to shell quoting, which is hard to parse without eval, would be to use some other character as separator in the output of your script. You'd need to pick one that is not needed in the actual arguments.



    Let's choose #, and have the script output foo bar#*#asdf. Now we can use unquoted command expansion to split the output of the command to the arguments.



    $ IFS='#'                          # split on '#' signs
    $ set -f # disable globbing
    $ args=( $( ./gen_args3.sh ) ) # assign the values to the array
    $ for var in "${args[@]}"; do printf ":%s:n" "$var"; done
    :foo bar:
    :*:
    :asdf:


    You'll need to set IFS back later if you depend on word splitting elsewhere in the script (unset IFS should work to make it the default), and also use set +f if you want to use globbing later.



    If you're not using Bash or some other shell that has arrays, you could use the positional parameters for that. Replace args=( $(...) ) with set -- $(./gen_args.sh) and use "$@" instead of "${args[@]}" then.






    share|improve this answer
















    I wrote a script which can generate those arguments for me, with quotes




    If the output is properly quoted for the shell, and you trust the output, then you could run eval on it.



    Assuming you have a shell that supports arrays, it would be best to use one to store the arguments you get.



    If ./gen_args.sh produces output like 'foo bar' '*' asdf, then we could run eval "args=( $(./gen_args.sh) )" to populate an array called args with the results. That would be the three elements foo bar, *, asdf.



    We can use "${args[@]}" as usual to expand the array elements individually:



    $ eval "args=( $(./gen_args.sh) )"
    $ for var in "${args[@]}"; do printf ":%s:n" "$var"; done
    :foo bar:
    :*:
    :asdf:


    However, eval will happily run any shell substitutions, so $HOME in the output would expand to your home directory, and a command substitution would actually run a command in the shell running eval. An output of "$(date >&2)" would create a single empty array element and print the current date on stdout. This is a concern if gen_args.sh gets the data from some untrusted source, like another host over the network, file names created by other users. The output could include arbitrary commands. (If get_args.sh itself was malicious, it wouldn't need to output anything, it could just run the malicious commands directly.)





    An alternative to shell quoting, which is hard to parse without eval, would be to use some other character as separator in the output of your script. You'd need to pick one that is not needed in the actual arguments.



    Let's choose #, and have the script output foo bar#*#asdf. Now we can use unquoted command expansion to split the output of the command to the arguments.



    $ IFS='#'                          # split on '#' signs
    $ set -f # disable globbing
    $ args=( $( ./gen_args3.sh ) ) # assign the values to the array
    $ for var in "${args[@]}"; do printf ":%s:n" "$var"; done
    :foo bar:
    :*:
    :asdf:


    You'll need to set IFS back later if you depend on word splitting elsewhere in the script (unset IFS should work to make it the default), and also use set +f if you want to use globbing later.



    If you're not using Bash or some other shell that has arrays, you could use the positional parameters for that. Replace args=( $(...) ) with set -- $(./gen_args.sh) and use "$@" instead of "${args[@]}" then.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 1 hour ago

























    answered 2 hours ago









    ilkkachuilkkachu

    56.8k785157




    56.8k785157













    • Best of both worlds!

      – Olorin
      2 hours ago



















    • Best of both worlds!

      – Olorin
      2 hours ago

















    Best of both worlds!

    – Olorin
    2 hours ago





    Best of both worlds!

    – Olorin
    2 hours ago













    4














    If the somecommand output is in reliably good shell syntax, you can use eval:



    $ eval sh test.sh $(echo '"hello " "hi and bye"')
    hello
    hi and bye


    But you have to be sure that the output has valid quoting and such, otherwise you might end up running commands outside the script as well:



    $ cat test.sh 
    for var in "$@"
    do
    echo "|$var|"
    done
    $ ls
    bar baz test.sh
    $ eval sh test.sh $(echo '"hello " "hi and bye"; echo rm *')
    |hello |
    |hi and bye|
    rm bar baz test.sh


    Note that echo rm bar baz test.sh wasn't passed to the script (because of the ;) and was run as a separate command. I added the | around $var to highlight this.





    Generally, unless you can completely trust the output of somecommand, it's not possible to reliably use its output to build a command string.






    share|improve this answer




























      4














      If the somecommand output is in reliably good shell syntax, you can use eval:



      $ eval sh test.sh $(echo '"hello " "hi and bye"')
      hello
      hi and bye


      But you have to be sure that the output has valid quoting and such, otherwise you might end up running commands outside the script as well:



      $ cat test.sh 
      for var in "$@"
      do
      echo "|$var|"
      done
      $ ls
      bar baz test.sh
      $ eval sh test.sh $(echo '"hello " "hi and bye"; echo rm *')
      |hello |
      |hi and bye|
      rm bar baz test.sh


      Note that echo rm bar baz test.sh wasn't passed to the script (because of the ;) and was run as a separate command. I added the | around $var to highlight this.





      Generally, unless you can completely trust the output of somecommand, it's not possible to reliably use its output to build a command string.






      share|improve this answer


























        4












        4








        4







        If the somecommand output is in reliably good shell syntax, you can use eval:



        $ eval sh test.sh $(echo '"hello " "hi and bye"')
        hello
        hi and bye


        But you have to be sure that the output has valid quoting and such, otherwise you might end up running commands outside the script as well:



        $ cat test.sh 
        for var in "$@"
        do
        echo "|$var|"
        done
        $ ls
        bar baz test.sh
        $ eval sh test.sh $(echo '"hello " "hi and bye"; echo rm *')
        |hello |
        |hi and bye|
        rm bar baz test.sh


        Note that echo rm bar baz test.sh wasn't passed to the script (because of the ;) and was run as a separate command. I added the | around $var to highlight this.





        Generally, unless you can completely trust the output of somecommand, it's not possible to reliably use its output to build a command string.






        share|improve this answer













        If the somecommand output is in reliably good shell syntax, you can use eval:



        $ eval sh test.sh $(echo '"hello " "hi and bye"')
        hello
        hi and bye


        But you have to be sure that the output has valid quoting and such, otherwise you might end up running commands outside the script as well:



        $ cat test.sh 
        for var in "$@"
        do
        echo "|$var|"
        done
        $ ls
        bar baz test.sh
        $ eval sh test.sh $(echo '"hello " "hi and bye"; echo rm *')
        |hello |
        |hi and bye|
        rm bar baz test.sh


        Note that echo rm bar baz test.sh wasn't passed to the script (because of the ;) and was run as a separate command. I added the | around $var to highlight this.





        Generally, unless you can completely trust the output of somecommand, it's not possible to reliably use its output to build a command string.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 2 hours ago









        OlorinOlorin

        1,779313




        1,779313























            3














            The issue is that once your somecommand script outputs the options, it's really just text and at the mercy of the shell's standard parsing (affected by whatever $IFS happens to be and what shell options are in effect).



            Instead of using somecommand to output the options, it would be easier, safer, and more robust to use it to call othercommand.



            In bash, ksh or zsh, you could then easily use an array to hold the individual options inside somecommand like so:



            options=( "hi there" "nice weather" "here's a star" "*" )
            options+=( "bonus bumblebee!" ) # add additional option


            Then call othercommand (still within somecommand):



            othercommand "${options[@]}"


            The expansion of "${options[@]}" would ensure that each element of the options array is individually quoted and presented to othercommand as separate arguments.



            In /bin/sh, use $@ to hold the options:



            set -- "hi there" "nice weather" "here's a star" "*"
            set -- "$@" "bonus bumblebee!" # add additional option

            othercommand "$@"


            (set is the command used for setting the positional parameters $1, $2, $3 etc. These are what makes up the array $@ in a standard POSIX shell. The initial -- is to signal to set that there are no options given, only arguments. The -- is really only needed if the first value happens to be something starting with -).



            Note that it's the double quotes around $@ and ${options[@]} that ensures that the elements are not individually word-splitted (and filename globbed).






            share|improve this answer


























            • could you explain set -- ?

              – user1207217
              2 hours ago











            • @user1207217 Added explanation to answer.

              – Kusalananda
              2 hours ago
















            3














            The issue is that once your somecommand script outputs the options, it's really just text and at the mercy of the shell's standard parsing (affected by whatever $IFS happens to be and what shell options are in effect).



            Instead of using somecommand to output the options, it would be easier, safer, and more robust to use it to call othercommand.



            In bash, ksh or zsh, you could then easily use an array to hold the individual options inside somecommand like so:



            options=( "hi there" "nice weather" "here's a star" "*" )
            options+=( "bonus bumblebee!" ) # add additional option


            Then call othercommand (still within somecommand):



            othercommand "${options[@]}"


            The expansion of "${options[@]}" would ensure that each element of the options array is individually quoted and presented to othercommand as separate arguments.



            In /bin/sh, use $@ to hold the options:



            set -- "hi there" "nice weather" "here's a star" "*"
            set -- "$@" "bonus bumblebee!" # add additional option

            othercommand "$@"


            (set is the command used for setting the positional parameters $1, $2, $3 etc. These are what makes up the array $@ in a standard POSIX shell. The initial -- is to signal to set that there are no options given, only arguments. The -- is really only needed if the first value happens to be something starting with -).



            Note that it's the double quotes around $@ and ${options[@]} that ensures that the elements are not individually word-splitted (and filename globbed).






            share|improve this answer


























            • could you explain set -- ?

              – user1207217
              2 hours ago











            • @user1207217 Added explanation to answer.

              – Kusalananda
              2 hours ago














            3












            3








            3







            The issue is that once your somecommand script outputs the options, it's really just text and at the mercy of the shell's standard parsing (affected by whatever $IFS happens to be and what shell options are in effect).



            Instead of using somecommand to output the options, it would be easier, safer, and more robust to use it to call othercommand.



            In bash, ksh or zsh, you could then easily use an array to hold the individual options inside somecommand like so:



            options=( "hi there" "nice weather" "here's a star" "*" )
            options+=( "bonus bumblebee!" ) # add additional option


            Then call othercommand (still within somecommand):



            othercommand "${options[@]}"


            The expansion of "${options[@]}" would ensure that each element of the options array is individually quoted and presented to othercommand as separate arguments.



            In /bin/sh, use $@ to hold the options:



            set -- "hi there" "nice weather" "here's a star" "*"
            set -- "$@" "bonus bumblebee!" # add additional option

            othercommand "$@"


            (set is the command used for setting the positional parameters $1, $2, $3 etc. These are what makes up the array $@ in a standard POSIX shell. The initial -- is to signal to set that there are no options given, only arguments. The -- is really only needed if the first value happens to be something starting with -).



            Note that it's the double quotes around $@ and ${options[@]} that ensures that the elements are not individually word-splitted (and filename globbed).






            share|improve this answer















            The issue is that once your somecommand script outputs the options, it's really just text and at the mercy of the shell's standard parsing (affected by whatever $IFS happens to be and what shell options are in effect).



            Instead of using somecommand to output the options, it would be easier, safer, and more robust to use it to call othercommand.



            In bash, ksh or zsh, you could then easily use an array to hold the individual options inside somecommand like so:



            options=( "hi there" "nice weather" "here's a star" "*" )
            options+=( "bonus bumblebee!" ) # add additional option


            Then call othercommand (still within somecommand):



            othercommand "${options[@]}"


            The expansion of "${options[@]}" would ensure that each element of the options array is individually quoted and presented to othercommand as separate arguments.



            In /bin/sh, use $@ to hold the options:



            set -- "hi there" "nice weather" "here's a star" "*"
            set -- "$@" "bonus bumblebee!" # add additional option

            othercommand "$@"


            (set is the command used for setting the positional parameters $1, $2, $3 etc. These are what makes up the array $@ in a standard POSIX shell. The initial -- is to signal to set that there are no options given, only arguments. The -- is really only needed if the first value happens to be something starting with -).



            Note that it's the double quotes around $@ and ${options[@]} that ensures that the elements are not individually word-splitted (and filename globbed).







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 1 hour ago

























            answered 3 hours ago









            KusalanandaKusalananda

            125k16236389




            125k16236389













            • could you explain set -- ?

              – user1207217
              2 hours ago











            • @user1207217 Added explanation to answer.

              – Kusalananda
              2 hours ago



















            • could you explain set -- ?

              – user1207217
              2 hours ago











            • @user1207217 Added explanation to answer.

              – Kusalananda
              2 hours ago

















            could you explain set -- ?

            – user1207217
            2 hours ago





            could you explain set -- ?

            – user1207217
            2 hours ago













            @user1207217 Added explanation to answer.

            – Kusalananda
            2 hours ago





            @user1207217 Added explanation to answer.

            – Kusalananda
            2 hours ago


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Unix & Linux Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f495769%2fhow-can-i-generate-arguments-to-another-command-via-command-substitution%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

            SQL Server 17 - Attemping to backup to remote NAS but Access is denied

            Always On Availability groups resolving state after failover - Remote harden of transaction...

            Restoring from pg_dump with foreign key constraints