How can I expand a quoted variable to nothing if it's empty?











up vote
14
down vote

favorite
3












Say I have a script doing:



some-command "$var1" "$var2" ...


And, in the event that var1 is empty, I'd rather that it be replaced with nothing instead of the empty string, so that the command executed is:



some-command "$var2" ...


and not:



some-command '' "$var2" ...


Is there a simpler way than testing the variable and conditionally including it?



if [ -n "$1" ]; then
some-command "$var1" "$var2" ...
# or some variant using arrays to build the command
# args+=("$var1")
else
some-command "$var2" ...
fi


Is there a parameter substitution than can expand to nothing in bash, zsh, or the like? I might still want to use globbing in the rest of the arguments, so disabling that and unquoting the variable is not an option.










share|improve this question
























  • I knew I had seen and probably used this before, but it proved difficult to search. Now that Michael showed the syntax, I remembered where I'd first seen it quickly enough: unix.stackexchange.com/a/269549/70524, unix.stackexchange.com/q/68484/70524
    – muru
    Jan 10 at 7:25










  • If you know it is some kind of parameter substitution, why didn't you look into the parameter expansion section of the man page? (-;
    – Philippos
    Jan 10 at 8:29






  • 1




    @Philippos I didn't know what it was at the time, only that I'd seen or used it before. Known knowns and unknown knowns. :(
    – muru
    Jan 10 at 8:33






  • 1




    extra cookie points for mentioning using an array to hold the arguments in the question itself.
    – ilkkachu
    Jan 10 at 15:12















up vote
14
down vote

favorite
3












Say I have a script doing:



some-command "$var1" "$var2" ...


And, in the event that var1 is empty, I'd rather that it be replaced with nothing instead of the empty string, so that the command executed is:



some-command "$var2" ...


and not:



some-command '' "$var2" ...


Is there a simpler way than testing the variable and conditionally including it?



if [ -n "$1" ]; then
some-command "$var1" "$var2" ...
# or some variant using arrays to build the command
# args+=("$var1")
else
some-command "$var2" ...
fi


Is there a parameter substitution than can expand to nothing in bash, zsh, or the like? I might still want to use globbing in the rest of the arguments, so disabling that and unquoting the variable is not an option.










share|improve this question
























  • I knew I had seen and probably used this before, but it proved difficult to search. Now that Michael showed the syntax, I remembered where I'd first seen it quickly enough: unix.stackexchange.com/a/269549/70524, unix.stackexchange.com/q/68484/70524
    – muru
    Jan 10 at 7:25










  • If you know it is some kind of parameter substitution, why didn't you look into the parameter expansion section of the man page? (-;
    – Philippos
    Jan 10 at 8:29






  • 1




    @Philippos I didn't know what it was at the time, only that I'd seen or used it before. Known knowns and unknown knowns. :(
    – muru
    Jan 10 at 8:33






  • 1




    extra cookie points for mentioning using an array to hold the arguments in the question itself.
    – ilkkachu
    Jan 10 at 15:12













up vote
14
down vote

favorite
3









up vote
14
down vote

favorite
3






3





Say I have a script doing:



some-command "$var1" "$var2" ...


And, in the event that var1 is empty, I'd rather that it be replaced with nothing instead of the empty string, so that the command executed is:



some-command "$var2" ...


and not:



some-command '' "$var2" ...


Is there a simpler way than testing the variable and conditionally including it?



if [ -n "$1" ]; then
some-command "$var1" "$var2" ...
# or some variant using arrays to build the command
# args+=("$var1")
else
some-command "$var2" ...
fi


Is there a parameter substitution than can expand to nothing in bash, zsh, or the like? I might still want to use globbing in the rest of the arguments, so disabling that and unquoting the variable is not an option.










share|improve this question















Say I have a script doing:



some-command "$var1" "$var2" ...


And, in the event that var1 is empty, I'd rather that it be replaced with nothing instead of the empty string, so that the command executed is:



some-command "$var2" ...


and not:



some-command '' "$var2" ...


Is there a simpler way than testing the variable and conditionally including it?



if [ -n "$1" ]; then
some-command "$var1" "$var2" ...
# or some variant using arrays to build the command
# args+=("$var1")
else
some-command "$var2" ...
fi


Is there a parameter substitution than can expand to nothing in bash, zsh, or the like? I might still want to use globbing in the rest of the arguments, so disabling that and unquoting the variable is not an option.







bash shell-script zsh variable






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 10 at 8:26









Michael Homer

44.5k7117155




44.5k7117155










asked Jan 10 at 6:44









muru

34.8k580153




34.8k580153












  • I knew I had seen and probably used this before, but it proved difficult to search. Now that Michael showed the syntax, I remembered where I'd first seen it quickly enough: unix.stackexchange.com/a/269549/70524, unix.stackexchange.com/q/68484/70524
    – muru
    Jan 10 at 7:25










  • If you know it is some kind of parameter substitution, why didn't you look into the parameter expansion section of the man page? (-;
    – Philippos
    Jan 10 at 8:29






  • 1




    @Philippos I didn't know what it was at the time, only that I'd seen or used it before. Known knowns and unknown knowns. :(
    – muru
    Jan 10 at 8:33






  • 1




    extra cookie points for mentioning using an array to hold the arguments in the question itself.
    – ilkkachu
    Jan 10 at 15:12


















  • I knew I had seen and probably used this before, but it proved difficult to search. Now that Michael showed the syntax, I remembered where I'd first seen it quickly enough: unix.stackexchange.com/a/269549/70524, unix.stackexchange.com/q/68484/70524
    – muru
    Jan 10 at 7:25










  • If you know it is some kind of parameter substitution, why didn't you look into the parameter expansion section of the man page? (-;
    – Philippos
    Jan 10 at 8:29






  • 1




    @Philippos I didn't know what it was at the time, only that I'd seen or used it before. Known knowns and unknown knowns. :(
    – muru
    Jan 10 at 8:33






  • 1




    extra cookie points for mentioning using an array to hold the arguments in the question itself.
    – ilkkachu
    Jan 10 at 15:12
















I knew I had seen and probably used this before, but it proved difficult to search. Now that Michael showed the syntax, I remembered where I'd first seen it quickly enough: unix.stackexchange.com/a/269549/70524, unix.stackexchange.com/q/68484/70524
– muru
Jan 10 at 7:25




I knew I had seen and probably used this before, but it proved difficult to search. Now that Michael showed the syntax, I remembered where I'd first seen it quickly enough: unix.stackexchange.com/a/269549/70524, unix.stackexchange.com/q/68484/70524
– muru
Jan 10 at 7:25












If you know it is some kind of parameter substitution, why didn't you look into the parameter expansion section of the man page? (-;
– Philippos
Jan 10 at 8:29




If you know it is some kind of parameter substitution, why didn't you look into the parameter expansion section of the man page? (-;
– Philippos
Jan 10 at 8:29




1




1




@Philippos I didn't know what it was at the time, only that I'd seen or used it before. Known knowns and unknown knowns. :(
– muru
Jan 10 at 8:33




@Philippos I didn't know what it was at the time, only that I'd seen or used it before. Known knowns and unknown knowns. :(
– muru
Jan 10 at 8:33




1




1




extra cookie points for mentioning using an array to hold the arguments in the question itself.
– ilkkachu
Jan 10 at 15:12




extra cookie points for mentioning using an array to hold the arguments in the question itself.
– ilkkachu
Jan 10 at 15:12










3 Answers
3






active

oldest

votes

















up vote
22
down vote



accepted










Posix compliant shells and Bash have ${parameter:+word}:




If parameter is unset or null, null shall be substituted; otherwise, the expansion of word (or an empty string if word is omitted) shall be substituted.




So you can just do:



${var1:+"$var1"}


and have var1 be checked, and "$var1" be used if it's set and non-empty (with the ordinary double-quoting rules). Otherwise it expands to nothing. Note that only the inner part is quoted here, not the whole thing.



The same also works in zsh. You have to repeat the variable, so it's not ideal, but it works out exactly as you wanted.



If you want a set-but-empty variable to expand to an empty argument, use ${var1+"$var1"} instead.






share|improve this answer



















  • 1




    Good enough for me. So, in this, the whole thing is not quoted, only the word part is.
    – muru
    Jan 10 at 6:57






  • 1




    As the question asked for "bash, zsh, or the like" (and for the Q&A archive), I edited to reflect that this is a posix feature. Even, if you add a /bash tag to the question after my comment. (-;
    – Philippos
    Jan 10 at 8:25








  • 2




    I took the liberty of editing in the difference between :+ and +.
    – ilkkachu
    Jan 10 at 15:16










  • Thanks much for a POSIX-compliant solution! I try to use sh/dash for potential chokepoint scripts, so I always appreciate it when someone shows how a thing is possible without resorting to Bash.
    – JamesTheAwesomeDude
    May 29 at 20:19


















up vote
3
down vote













That's what zsh does by default when you omit the quotes:



some-command $var1 $var2


Actually, the only reason why you still need quotes in zsh around parameter expansion is to avoid that behaviour (the empty removal) as zsh doesn't have the other problems that affect other shells when you don't quote parameter expansions (the implicit split+glob).



You can do the same with other POSIX-like shells if you disable split and glob:



(IFS=; set -o noglob; some-command $var1 $var2)


Now, I'd argue that if your variable can have either 0 or 1 value, it should be an array and not a scalar variable and use:



some-command "${var1[@]}" "${var2[@]}"


And use var1=(value) when var1 is to contain one value, var1=('') when it's to contain one empty value, and var1=() when it's to contain no value.






share|improve this answer






























    up vote
    0
    down vote













    I ran into this using rsync in a bash script that started the command with or without a -n to toggle dry runs. It turns out that rsync and a number of gnu commands take '' as a valid first argument and act differently than if it were not there.



    This took quite awhile to debug as null parameters are almost completely invisible.



    Someone on the rsync list showed me a way to avoid this problem while also greatly simplifying my coding. If I understand it correctly, this is a variation on @Stéphane Chazelas's last suggestion.



    Build your command arguments in a number of separate variables. These can be set in any order or logic that suits the problem.



    Then, at the end, use the variables to construct an array with everything in its proper place and use that as arguments to the actual command.



    This way the command is only issued at one place in the code instead of being repeated for each variation of the arguments.



    Any variable that is empty just disappears using this method.



    I know using eval is highly frowned upon. I don't remember all the details, but I seemed to need it to get things to work this way - something to do with handling parameters with embedded white space.



    Example:



    dry_run=''
    if [[ it is a test run ]]
    then
    dry_run='-n'
    fi
    ...
    rsync_options=(
    ${dry_run}
    -avushi
    ${delete}
    ${excludes}
    --stats
    --progress
    )
    ...
    eval rsync "${rsync_options[@]}" ...





    share|improve this answer





















    • That's a worse way of doing what I described in the question (building an array of arguments conditionally). By leaving the variables unquoted, who knows what problems you're leaving yourself open to.
      – muru
      Jan 13 at 15:35










    • @muru You're right, but I still need something like this. I don't quite see how to fix it using the techniques from the other answers. It would be great to see a code fragment done the right way that puts it all together. I'm going to play with Stephane's last option later as that might do what I want.
      – Joe
      Jan 14 at 10:20










    • Like paste.ubuntu.com/26383847?
      – muru
      Jan 14 at 10:31










    • Just got back to this. Thanks for the example. It makes sense. I'm going to work with it.
      – Joe
      Mar 9 at 5:11











    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: 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%2f415990%2fhow-can-i-expand-a-quoted-variable-to-nothing-if-its-empty%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








    up vote
    22
    down vote



    accepted










    Posix compliant shells and Bash have ${parameter:+word}:




    If parameter is unset or null, null shall be substituted; otherwise, the expansion of word (or an empty string if word is omitted) shall be substituted.




    So you can just do:



    ${var1:+"$var1"}


    and have var1 be checked, and "$var1" be used if it's set and non-empty (with the ordinary double-quoting rules). Otherwise it expands to nothing. Note that only the inner part is quoted here, not the whole thing.



    The same also works in zsh. You have to repeat the variable, so it's not ideal, but it works out exactly as you wanted.



    If you want a set-but-empty variable to expand to an empty argument, use ${var1+"$var1"} instead.






    share|improve this answer



















    • 1




      Good enough for me. So, in this, the whole thing is not quoted, only the word part is.
      – muru
      Jan 10 at 6:57






    • 1




      As the question asked for "bash, zsh, or the like" (and for the Q&A archive), I edited to reflect that this is a posix feature. Even, if you add a /bash tag to the question after my comment. (-;
      – Philippos
      Jan 10 at 8:25








    • 2




      I took the liberty of editing in the difference between :+ and +.
      – ilkkachu
      Jan 10 at 15:16










    • Thanks much for a POSIX-compliant solution! I try to use sh/dash for potential chokepoint scripts, so I always appreciate it when someone shows how a thing is possible without resorting to Bash.
      – JamesTheAwesomeDude
      May 29 at 20:19















    up vote
    22
    down vote



    accepted










    Posix compliant shells and Bash have ${parameter:+word}:




    If parameter is unset or null, null shall be substituted; otherwise, the expansion of word (or an empty string if word is omitted) shall be substituted.




    So you can just do:



    ${var1:+"$var1"}


    and have var1 be checked, and "$var1" be used if it's set and non-empty (with the ordinary double-quoting rules). Otherwise it expands to nothing. Note that only the inner part is quoted here, not the whole thing.



    The same also works in zsh. You have to repeat the variable, so it's not ideal, but it works out exactly as you wanted.



    If you want a set-but-empty variable to expand to an empty argument, use ${var1+"$var1"} instead.






    share|improve this answer



















    • 1




      Good enough for me. So, in this, the whole thing is not quoted, only the word part is.
      – muru
      Jan 10 at 6:57






    • 1




      As the question asked for "bash, zsh, or the like" (and for the Q&A archive), I edited to reflect that this is a posix feature. Even, if you add a /bash tag to the question after my comment. (-;
      – Philippos
      Jan 10 at 8:25








    • 2




      I took the liberty of editing in the difference between :+ and +.
      – ilkkachu
      Jan 10 at 15:16










    • Thanks much for a POSIX-compliant solution! I try to use sh/dash for potential chokepoint scripts, so I always appreciate it when someone shows how a thing is possible without resorting to Bash.
      – JamesTheAwesomeDude
      May 29 at 20:19













    up vote
    22
    down vote



    accepted







    up vote
    22
    down vote



    accepted






    Posix compliant shells and Bash have ${parameter:+word}:




    If parameter is unset or null, null shall be substituted; otherwise, the expansion of word (or an empty string if word is omitted) shall be substituted.




    So you can just do:



    ${var1:+"$var1"}


    and have var1 be checked, and "$var1" be used if it's set and non-empty (with the ordinary double-quoting rules). Otherwise it expands to nothing. Note that only the inner part is quoted here, not the whole thing.



    The same also works in zsh. You have to repeat the variable, so it's not ideal, but it works out exactly as you wanted.



    If you want a set-but-empty variable to expand to an empty argument, use ${var1+"$var1"} instead.






    share|improve this answer














    Posix compliant shells and Bash have ${parameter:+word}:




    If parameter is unset or null, null shall be substituted; otherwise, the expansion of word (or an empty string if word is omitted) shall be substituted.




    So you can just do:



    ${var1:+"$var1"}


    and have var1 be checked, and "$var1" be used if it's set and non-empty (with the ordinary double-quoting rules). Otherwise it expands to nothing. Note that only the inner part is quoted here, not the whole thing.



    The same also works in zsh. You have to repeat the variable, so it's not ideal, but it works out exactly as you wanted.



    If you want a set-but-empty variable to expand to an empty argument, use ${var1+"$var1"} instead.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jan 10 at 15:16









    ilkkachu

    53.7k781146




    53.7k781146










    answered Jan 10 at 6:51









    Michael Homer

    44.5k7117155




    44.5k7117155








    • 1




      Good enough for me. So, in this, the whole thing is not quoted, only the word part is.
      – muru
      Jan 10 at 6:57






    • 1




      As the question asked for "bash, zsh, or the like" (and for the Q&A archive), I edited to reflect that this is a posix feature. Even, if you add a /bash tag to the question after my comment. (-;
      – Philippos
      Jan 10 at 8:25








    • 2




      I took the liberty of editing in the difference between :+ and +.
      – ilkkachu
      Jan 10 at 15:16










    • Thanks much for a POSIX-compliant solution! I try to use sh/dash for potential chokepoint scripts, so I always appreciate it when someone shows how a thing is possible without resorting to Bash.
      – JamesTheAwesomeDude
      May 29 at 20:19














    • 1




      Good enough for me. So, in this, the whole thing is not quoted, only the word part is.
      – muru
      Jan 10 at 6:57






    • 1




      As the question asked for "bash, zsh, or the like" (and for the Q&A archive), I edited to reflect that this is a posix feature. Even, if you add a /bash tag to the question after my comment. (-;
      – Philippos
      Jan 10 at 8:25








    • 2




      I took the liberty of editing in the difference between :+ and +.
      – ilkkachu
      Jan 10 at 15:16










    • Thanks much for a POSIX-compliant solution! I try to use sh/dash for potential chokepoint scripts, so I always appreciate it when someone shows how a thing is possible without resorting to Bash.
      – JamesTheAwesomeDude
      May 29 at 20:19








    1




    1




    Good enough for me. So, in this, the whole thing is not quoted, only the word part is.
    – muru
    Jan 10 at 6:57




    Good enough for me. So, in this, the whole thing is not quoted, only the word part is.
    – muru
    Jan 10 at 6:57




    1




    1




    As the question asked for "bash, zsh, or the like" (and for the Q&A archive), I edited to reflect that this is a posix feature. Even, if you add a /bash tag to the question after my comment. (-;
    – Philippos
    Jan 10 at 8:25






    As the question asked for "bash, zsh, or the like" (and for the Q&A archive), I edited to reflect that this is a posix feature. Even, if you add a /bash tag to the question after my comment. (-;
    – Philippos
    Jan 10 at 8:25






    2




    2




    I took the liberty of editing in the difference between :+ and +.
    – ilkkachu
    Jan 10 at 15:16




    I took the liberty of editing in the difference between :+ and +.
    – ilkkachu
    Jan 10 at 15:16












    Thanks much for a POSIX-compliant solution! I try to use sh/dash for potential chokepoint scripts, so I always appreciate it when someone shows how a thing is possible without resorting to Bash.
    – JamesTheAwesomeDude
    May 29 at 20:19




    Thanks much for a POSIX-compliant solution! I try to use sh/dash for potential chokepoint scripts, so I always appreciate it when someone shows how a thing is possible without resorting to Bash.
    – JamesTheAwesomeDude
    May 29 at 20:19












    up vote
    3
    down vote













    That's what zsh does by default when you omit the quotes:



    some-command $var1 $var2


    Actually, the only reason why you still need quotes in zsh around parameter expansion is to avoid that behaviour (the empty removal) as zsh doesn't have the other problems that affect other shells when you don't quote parameter expansions (the implicit split+glob).



    You can do the same with other POSIX-like shells if you disable split and glob:



    (IFS=; set -o noglob; some-command $var1 $var2)


    Now, I'd argue that if your variable can have either 0 or 1 value, it should be an array and not a scalar variable and use:



    some-command "${var1[@]}" "${var2[@]}"


    And use var1=(value) when var1 is to contain one value, var1=('') when it's to contain one empty value, and var1=() when it's to contain no value.






    share|improve this answer



























      up vote
      3
      down vote













      That's what zsh does by default when you omit the quotes:



      some-command $var1 $var2


      Actually, the only reason why you still need quotes in zsh around parameter expansion is to avoid that behaviour (the empty removal) as zsh doesn't have the other problems that affect other shells when you don't quote parameter expansions (the implicit split+glob).



      You can do the same with other POSIX-like shells if you disable split and glob:



      (IFS=; set -o noglob; some-command $var1 $var2)


      Now, I'd argue that if your variable can have either 0 or 1 value, it should be an array and not a scalar variable and use:



      some-command "${var1[@]}" "${var2[@]}"


      And use var1=(value) when var1 is to contain one value, var1=('') when it's to contain one empty value, and var1=() when it's to contain no value.






      share|improve this answer

























        up vote
        3
        down vote










        up vote
        3
        down vote









        That's what zsh does by default when you omit the quotes:



        some-command $var1 $var2


        Actually, the only reason why you still need quotes in zsh around parameter expansion is to avoid that behaviour (the empty removal) as zsh doesn't have the other problems that affect other shells when you don't quote parameter expansions (the implicit split+glob).



        You can do the same with other POSIX-like shells if you disable split and glob:



        (IFS=; set -o noglob; some-command $var1 $var2)


        Now, I'd argue that if your variable can have either 0 or 1 value, it should be an array and not a scalar variable and use:



        some-command "${var1[@]}" "${var2[@]}"


        And use var1=(value) when var1 is to contain one value, var1=('') when it's to contain one empty value, and var1=() when it's to contain no value.






        share|improve this answer














        That's what zsh does by default when you omit the quotes:



        some-command $var1 $var2


        Actually, the only reason why you still need quotes in zsh around parameter expansion is to avoid that behaviour (the empty removal) as zsh doesn't have the other problems that affect other shells when you don't quote parameter expansions (the implicit split+glob).



        You can do the same with other POSIX-like shells if you disable split and glob:



        (IFS=; set -o noglob; some-command $var1 $var2)


        Now, I'd argue that if your variable can have either 0 or 1 value, it should be an array and not a scalar variable and use:



        some-command "${var1[@]}" "${var2[@]}"


        And use var1=(value) when var1 is to contain one value, var1=('') when it's to contain one empty value, and var1=() when it's to contain no value.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Jan 14 at 9:24

























        answered Jan 11 at 22:05









        Stéphane Chazelas

        293k54551893




        293k54551893






















            up vote
            0
            down vote













            I ran into this using rsync in a bash script that started the command with or without a -n to toggle dry runs. It turns out that rsync and a number of gnu commands take '' as a valid first argument and act differently than if it were not there.



            This took quite awhile to debug as null parameters are almost completely invisible.



            Someone on the rsync list showed me a way to avoid this problem while also greatly simplifying my coding. If I understand it correctly, this is a variation on @Stéphane Chazelas's last suggestion.



            Build your command arguments in a number of separate variables. These can be set in any order or logic that suits the problem.



            Then, at the end, use the variables to construct an array with everything in its proper place and use that as arguments to the actual command.



            This way the command is only issued at one place in the code instead of being repeated for each variation of the arguments.



            Any variable that is empty just disappears using this method.



            I know using eval is highly frowned upon. I don't remember all the details, but I seemed to need it to get things to work this way - something to do with handling parameters with embedded white space.



            Example:



            dry_run=''
            if [[ it is a test run ]]
            then
            dry_run='-n'
            fi
            ...
            rsync_options=(
            ${dry_run}
            -avushi
            ${delete}
            ${excludes}
            --stats
            --progress
            )
            ...
            eval rsync "${rsync_options[@]}" ...





            share|improve this answer





















            • That's a worse way of doing what I described in the question (building an array of arguments conditionally). By leaving the variables unquoted, who knows what problems you're leaving yourself open to.
              – muru
              Jan 13 at 15:35










            • @muru You're right, but I still need something like this. I don't quite see how to fix it using the techniques from the other answers. It would be great to see a code fragment done the right way that puts it all together. I'm going to play with Stephane's last option later as that might do what I want.
              – Joe
              Jan 14 at 10:20










            • Like paste.ubuntu.com/26383847?
              – muru
              Jan 14 at 10:31










            • Just got back to this. Thanks for the example. It makes sense. I'm going to work with it.
              – Joe
              Mar 9 at 5:11















            up vote
            0
            down vote













            I ran into this using rsync in a bash script that started the command with or without a -n to toggle dry runs. It turns out that rsync and a number of gnu commands take '' as a valid first argument and act differently than if it were not there.



            This took quite awhile to debug as null parameters are almost completely invisible.



            Someone on the rsync list showed me a way to avoid this problem while also greatly simplifying my coding. If I understand it correctly, this is a variation on @Stéphane Chazelas's last suggestion.



            Build your command arguments in a number of separate variables. These can be set in any order or logic that suits the problem.



            Then, at the end, use the variables to construct an array with everything in its proper place and use that as arguments to the actual command.



            This way the command is only issued at one place in the code instead of being repeated for each variation of the arguments.



            Any variable that is empty just disappears using this method.



            I know using eval is highly frowned upon. I don't remember all the details, but I seemed to need it to get things to work this way - something to do with handling parameters with embedded white space.



            Example:



            dry_run=''
            if [[ it is a test run ]]
            then
            dry_run='-n'
            fi
            ...
            rsync_options=(
            ${dry_run}
            -avushi
            ${delete}
            ${excludes}
            --stats
            --progress
            )
            ...
            eval rsync "${rsync_options[@]}" ...





            share|improve this answer





















            • That's a worse way of doing what I described in the question (building an array of arguments conditionally). By leaving the variables unquoted, who knows what problems you're leaving yourself open to.
              – muru
              Jan 13 at 15:35










            • @muru You're right, but I still need something like this. I don't quite see how to fix it using the techniques from the other answers. It would be great to see a code fragment done the right way that puts it all together. I'm going to play with Stephane's last option later as that might do what I want.
              – Joe
              Jan 14 at 10:20










            • Like paste.ubuntu.com/26383847?
              – muru
              Jan 14 at 10:31










            • Just got back to this. Thanks for the example. It makes sense. I'm going to work with it.
              – Joe
              Mar 9 at 5:11













            up vote
            0
            down vote










            up vote
            0
            down vote









            I ran into this using rsync in a bash script that started the command with or without a -n to toggle dry runs. It turns out that rsync and a number of gnu commands take '' as a valid first argument and act differently than if it were not there.



            This took quite awhile to debug as null parameters are almost completely invisible.



            Someone on the rsync list showed me a way to avoid this problem while also greatly simplifying my coding. If I understand it correctly, this is a variation on @Stéphane Chazelas's last suggestion.



            Build your command arguments in a number of separate variables. These can be set in any order or logic that suits the problem.



            Then, at the end, use the variables to construct an array with everything in its proper place and use that as arguments to the actual command.



            This way the command is only issued at one place in the code instead of being repeated for each variation of the arguments.



            Any variable that is empty just disappears using this method.



            I know using eval is highly frowned upon. I don't remember all the details, but I seemed to need it to get things to work this way - something to do with handling parameters with embedded white space.



            Example:



            dry_run=''
            if [[ it is a test run ]]
            then
            dry_run='-n'
            fi
            ...
            rsync_options=(
            ${dry_run}
            -avushi
            ${delete}
            ${excludes}
            --stats
            --progress
            )
            ...
            eval rsync "${rsync_options[@]}" ...





            share|improve this answer












            I ran into this using rsync in a bash script that started the command with or without a -n to toggle dry runs. It turns out that rsync and a number of gnu commands take '' as a valid first argument and act differently than if it were not there.



            This took quite awhile to debug as null parameters are almost completely invisible.



            Someone on the rsync list showed me a way to avoid this problem while also greatly simplifying my coding. If I understand it correctly, this is a variation on @Stéphane Chazelas's last suggestion.



            Build your command arguments in a number of separate variables. These can be set in any order or logic that suits the problem.



            Then, at the end, use the variables to construct an array with everything in its proper place and use that as arguments to the actual command.



            This way the command is only issued at one place in the code instead of being repeated for each variation of the arguments.



            Any variable that is empty just disappears using this method.



            I know using eval is highly frowned upon. I don't remember all the details, but I seemed to need it to get things to work this way - something to do with handling parameters with embedded white space.



            Example:



            dry_run=''
            if [[ it is a test run ]]
            then
            dry_run='-n'
            fi
            ...
            rsync_options=(
            ${dry_run}
            -avushi
            ${delete}
            ${excludes}
            --stats
            --progress
            )
            ...
            eval rsync "${rsync_options[@]}" ...






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jan 13 at 4:52









            Joe

            935816




            935816












            • That's a worse way of doing what I described in the question (building an array of arguments conditionally). By leaving the variables unquoted, who knows what problems you're leaving yourself open to.
              – muru
              Jan 13 at 15:35










            • @muru You're right, but I still need something like this. I don't quite see how to fix it using the techniques from the other answers. It would be great to see a code fragment done the right way that puts it all together. I'm going to play with Stephane's last option later as that might do what I want.
              – Joe
              Jan 14 at 10:20










            • Like paste.ubuntu.com/26383847?
              – muru
              Jan 14 at 10:31










            • Just got back to this. Thanks for the example. It makes sense. I'm going to work with it.
              – Joe
              Mar 9 at 5:11


















            • That's a worse way of doing what I described in the question (building an array of arguments conditionally). By leaving the variables unquoted, who knows what problems you're leaving yourself open to.
              – muru
              Jan 13 at 15:35










            • @muru You're right, but I still need something like this. I don't quite see how to fix it using the techniques from the other answers. It would be great to see a code fragment done the right way that puts it all together. I'm going to play with Stephane's last option later as that might do what I want.
              – Joe
              Jan 14 at 10:20










            • Like paste.ubuntu.com/26383847?
              – muru
              Jan 14 at 10:31










            • Just got back to this. Thanks for the example. It makes sense. I'm going to work with it.
              – Joe
              Mar 9 at 5:11
















            That's a worse way of doing what I described in the question (building an array of arguments conditionally). By leaving the variables unquoted, who knows what problems you're leaving yourself open to.
            – muru
            Jan 13 at 15:35




            That's a worse way of doing what I described in the question (building an array of arguments conditionally). By leaving the variables unquoted, who knows what problems you're leaving yourself open to.
            – muru
            Jan 13 at 15:35












            @muru You're right, but I still need something like this. I don't quite see how to fix it using the techniques from the other answers. It would be great to see a code fragment done the right way that puts it all together. I'm going to play with Stephane's last option later as that might do what I want.
            – Joe
            Jan 14 at 10:20




            @muru You're right, but I still need something like this. I don't quite see how to fix it using the techniques from the other answers. It would be great to see a code fragment done the right way that puts it all together. I'm going to play with Stephane's last option later as that might do what I want.
            – Joe
            Jan 14 at 10:20












            Like paste.ubuntu.com/26383847?
            – muru
            Jan 14 at 10:31




            Like paste.ubuntu.com/26383847?
            – muru
            Jan 14 at 10:31












            Just got back to this. Thanks for the example. It makes sense. I'm going to work with it.
            – Joe
            Mar 9 at 5:11




            Just got back to this. Thanks for the example. It makes sense. I'm going to work with it.
            – Joe
            Mar 9 at 5:11


















             

            draft saved


            draft discarded



















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f415990%2fhow-can-i-expand-a-quoted-variable-to-nothing-if-its-empty%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

            Accessing regular linux commands in Huawei's Dopra Linux

            Can't connect RFCOMM socket: Host is down

            Kernel panic - not syncing: Fatal Exception in Interrupt