How do I create a bash script that sums any number of command line arguments?












5















How would I create a bash script that the user can use to sum any amount of command line arguments? For example, say my script is called sum:



sum 3


3



sum 3 5


8



sum 9 8 21


38



And so on.. I realize that I will have to loop through the command line arguments and increment them to the total, but I am not really sure how to do that. I am not sure how to reference say the 2nd command line argument to a specific variable or how to get the number of total command line arguments.










share|improve this question

























  • The native bash feature won't handle floating point values (eg: 3.5). For that you'd need to use a program such as awk, python, dc, bc or perl. See @rici's answer.

    – NVRAM
    Nov 5 '13 at 17:12
















5















How would I create a bash script that the user can use to sum any amount of command line arguments? For example, say my script is called sum:



sum 3


3



sum 3 5


8



sum 9 8 21


38



And so on.. I realize that I will have to loop through the command line arguments and increment them to the total, but I am not really sure how to do that. I am not sure how to reference say the 2nd command line argument to a specific variable or how to get the number of total command line arguments.










share|improve this question

























  • The native bash feature won't handle floating point values (eg: 3.5). For that you'd need to use a program such as awk, python, dc, bc or perl. See @rici's answer.

    – NVRAM
    Nov 5 '13 at 17:12














5












5








5


1






How would I create a bash script that the user can use to sum any amount of command line arguments? For example, say my script is called sum:



sum 3


3



sum 3 5


8



sum 9 8 21


38



And so on.. I realize that I will have to loop through the command line arguments and increment them to the total, but I am not really sure how to do that. I am not sure how to reference say the 2nd command line argument to a specific variable or how to get the number of total command line arguments.










share|improve this question
















How would I create a bash script that the user can use to sum any amount of command line arguments? For example, say my script is called sum:



sum 3


3



sum 3 5


8



sum 9 8 21


38



And so on.. I realize that I will have to loop through the command line arguments and increment them to the total, but I am not really sure how to do that. I am not sure how to reference say the 2nd command line argument to a specific variable or how to get the number of total command line arguments.







bash shell-script arithmetic






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 5 '13 at 23:16









Gilles

542k12810991616




542k12810991616










asked Nov 5 '13 at 6:26









JohnJohn

93991924




93991924













  • The native bash feature won't handle floating point values (eg: 3.5). For that you'd need to use a program such as awk, python, dc, bc or perl. See @rici's answer.

    – NVRAM
    Nov 5 '13 at 17:12



















  • The native bash feature won't handle floating point values (eg: 3.5). For that you'd need to use a program such as awk, python, dc, bc or perl. See @rici's answer.

    – NVRAM
    Nov 5 '13 at 17:12

















The native bash feature won't handle floating point values (eg: 3.5). For that you'd need to use a program such as awk, python, dc, bc or perl. See @rici's answer.

– NVRAM
Nov 5 '13 at 17:12





The native bash feature won't handle floating point values (eg: 3.5). For that you'd need to use a program such as awk, python, dc, bc or perl. See @rici's answer.

– NVRAM
Nov 5 '13 at 17:12










3 Answers
3






active

oldest

votes


















13














No need for bash, plain sh will do as well:



#! /bin/sh - 
IFS=+; echo "$(($*))"


$* in POSIX shells, expands to the list of positional parameters (in this case, the arguments to the script) separated by the first character of $IFS (or space if $IFS is unset or nothing if $IFS is empty). $((...)) is the shell internal arithmetic expansion operator (note that it supports decimal, octal and hexadecimal numbers)



If you need floating point support, that's where you'll need a different shell like ksh93 or zsh (not bash as bash only supports integer arithmetic), though you could also use awk:



#! /usr/bin/awk -f
BEGIN {t=0; for (i in ARGV) t+=ARGV[i]; print t}


That will use double type numbers as implemented by your system. The input numbers must be decimal floating point or engineering notation in the English style (floating point delimiter is the period character regardless of the locale).



Some awk implementations like GNU awk when POSIXLY_CORRECT is in the environment also support hexadecimals including with binary exponent notations. Or with --non-decimal-data, it understands octals and hexadecimals:



$ POSIXLY_CORRECT=1 ./sum  0xap3 0xa
90 # (0xa * 2^3) + 0xa
$ awk --non-decimal-data -f ./sum 010
8





share|improve this answer


























  • clever. But I really hope you are not confusing him ^^ It seems he's learning shell scripting basics, and you throw him IFS manipulation ^^ It's always good to know, but probably a bit too early for him... Or provide explanations such as IFS=+ means afterward the "$*" will expand to "all the arguments separated by a '+'", hence the $((computation)) will be replaced with the sum of all arguments

    – Olivier Dulac
    Nov 5 '13 at 10:13





















8














A non-looping variant:



{ printf %d+ "$@"; echo 0; } | bc


Example



Put the above in a script file, sum.



#!/bin/bash

{ printf %d+ "$@"; echo 0; } | bc


Run it like so:



$ ./sum 4
4
$ ./sum 4 4 5
13





share|improve this answer

































    7














    You can use the following bash function:



    sum() {
    local sum=0
    for arg in "$@"; do
    (( sum += arg ))
    done
    echo $sum
    }





    share|improve this answer
























    • As a side question, is there a way to determine how many args are in the command line without looping?

      – John
      Nov 5 '13 at 7:13






    • 4





      $# is the number of args

      – rici
      Nov 5 '13 at 7:19











    • Thank you, perfect. One last question I forgot to clarify.. is there any way I can detect if it is like the very first argument? So say it is the very first argument, I can do something special with it. For example, as a random example, if the very first argument is a 7, I echo that the very first argument is a 7.

      – John
      Nov 5 '13 at 7:47






    • 2





      @John $1 is the first argument, $2 is the second argument, and so on. The variable $0 is the script's name. The total number of arguments is stored in $#. The variables $@ and $* return all the arguments. See also: how-to.wikia.com/wiki/…

      – Radu Rădeanu
      Nov 5 '13 at 8:04








    • 1





      @John typically if you want to process the first argument differently you first copy it to something else and then shift all the rest of the arguments with first=$1;shift

      – icarus
      Nov 19 '16 at 17:45











    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%2f98907%2fhow-do-i-create-a-bash-script-that-sums-any-number-of-command-line-arguments%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









    13














    No need for bash, plain sh will do as well:



    #! /bin/sh - 
    IFS=+; echo "$(($*))"


    $* in POSIX shells, expands to the list of positional parameters (in this case, the arguments to the script) separated by the first character of $IFS (or space if $IFS is unset or nothing if $IFS is empty). $((...)) is the shell internal arithmetic expansion operator (note that it supports decimal, octal and hexadecimal numbers)



    If you need floating point support, that's where you'll need a different shell like ksh93 or zsh (not bash as bash only supports integer arithmetic), though you could also use awk:



    #! /usr/bin/awk -f
    BEGIN {t=0; for (i in ARGV) t+=ARGV[i]; print t}


    That will use double type numbers as implemented by your system. The input numbers must be decimal floating point or engineering notation in the English style (floating point delimiter is the period character regardless of the locale).



    Some awk implementations like GNU awk when POSIXLY_CORRECT is in the environment also support hexadecimals including with binary exponent notations. Or with --non-decimal-data, it understands octals and hexadecimals:



    $ POSIXLY_CORRECT=1 ./sum  0xap3 0xa
    90 # (0xa * 2^3) + 0xa
    $ awk --non-decimal-data -f ./sum 010
    8





    share|improve this answer


























    • clever. But I really hope you are not confusing him ^^ It seems he's learning shell scripting basics, and you throw him IFS manipulation ^^ It's always good to know, but probably a bit too early for him... Or provide explanations such as IFS=+ means afterward the "$*" will expand to "all the arguments separated by a '+'", hence the $((computation)) will be replaced with the sum of all arguments

      – Olivier Dulac
      Nov 5 '13 at 10:13


















    13














    No need for bash, plain sh will do as well:



    #! /bin/sh - 
    IFS=+; echo "$(($*))"


    $* in POSIX shells, expands to the list of positional parameters (in this case, the arguments to the script) separated by the first character of $IFS (or space if $IFS is unset or nothing if $IFS is empty). $((...)) is the shell internal arithmetic expansion operator (note that it supports decimal, octal and hexadecimal numbers)



    If you need floating point support, that's where you'll need a different shell like ksh93 or zsh (not bash as bash only supports integer arithmetic), though you could also use awk:



    #! /usr/bin/awk -f
    BEGIN {t=0; for (i in ARGV) t+=ARGV[i]; print t}


    That will use double type numbers as implemented by your system. The input numbers must be decimal floating point or engineering notation in the English style (floating point delimiter is the period character regardless of the locale).



    Some awk implementations like GNU awk when POSIXLY_CORRECT is in the environment also support hexadecimals including with binary exponent notations. Or with --non-decimal-data, it understands octals and hexadecimals:



    $ POSIXLY_CORRECT=1 ./sum  0xap3 0xa
    90 # (0xa * 2^3) + 0xa
    $ awk --non-decimal-data -f ./sum 010
    8





    share|improve this answer


























    • clever. But I really hope you are not confusing him ^^ It seems he's learning shell scripting basics, and you throw him IFS manipulation ^^ It's always good to know, but probably a bit too early for him... Or provide explanations such as IFS=+ means afterward the "$*" will expand to "all the arguments separated by a '+'", hence the $((computation)) will be replaced with the sum of all arguments

      – Olivier Dulac
      Nov 5 '13 at 10:13
















    13












    13








    13







    No need for bash, plain sh will do as well:



    #! /bin/sh - 
    IFS=+; echo "$(($*))"


    $* in POSIX shells, expands to the list of positional parameters (in this case, the arguments to the script) separated by the first character of $IFS (or space if $IFS is unset or nothing if $IFS is empty). $((...)) is the shell internal arithmetic expansion operator (note that it supports decimal, octal and hexadecimal numbers)



    If you need floating point support, that's where you'll need a different shell like ksh93 or zsh (not bash as bash only supports integer arithmetic), though you could also use awk:



    #! /usr/bin/awk -f
    BEGIN {t=0; for (i in ARGV) t+=ARGV[i]; print t}


    That will use double type numbers as implemented by your system. The input numbers must be decimal floating point or engineering notation in the English style (floating point delimiter is the period character regardless of the locale).



    Some awk implementations like GNU awk when POSIXLY_CORRECT is in the environment also support hexadecimals including with binary exponent notations. Or with --non-decimal-data, it understands octals and hexadecimals:



    $ POSIXLY_CORRECT=1 ./sum  0xap3 0xa
    90 # (0xa * 2^3) + 0xa
    $ awk --non-decimal-data -f ./sum 010
    8





    share|improve this answer















    No need for bash, plain sh will do as well:



    #! /bin/sh - 
    IFS=+; echo "$(($*))"


    $* in POSIX shells, expands to the list of positional parameters (in this case, the arguments to the script) separated by the first character of $IFS (or space if $IFS is unset or nothing if $IFS is empty). $((...)) is the shell internal arithmetic expansion operator (note that it supports decimal, octal and hexadecimal numbers)



    If you need floating point support, that's where you'll need a different shell like ksh93 or zsh (not bash as bash only supports integer arithmetic), though you could also use awk:



    #! /usr/bin/awk -f
    BEGIN {t=0; for (i in ARGV) t+=ARGV[i]; print t}


    That will use double type numbers as implemented by your system. The input numbers must be decimal floating point or engineering notation in the English style (floating point delimiter is the period character regardless of the locale).



    Some awk implementations like GNU awk when POSIXLY_CORRECT is in the environment also support hexadecimals including with binary exponent notations. Or with --non-decimal-data, it understands octals and hexadecimals:



    $ POSIXLY_CORRECT=1 ./sum  0xap3 0xa
    90 # (0xa * 2^3) + 0xa
    $ awk --non-decimal-data -f ./sum 010
    8






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 7 mins ago

























    answered Nov 5 '13 at 9:51









    Stéphane ChazelasStéphane Chazelas

    310k57584945




    310k57584945













    • clever. But I really hope you are not confusing him ^^ It seems he's learning shell scripting basics, and you throw him IFS manipulation ^^ It's always good to know, but probably a bit too early for him... Or provide explanations such as IFS=+ means afterward the "$*" will expand to "all the arguments separated by a '+'", hence the $((computation)) will be replaced with the sum of all arguments

      – Olivier Dulac
      Nov 5 '13 at 10:13





















    • clever. But I really hope you are not confusing him ^^ It seems he's learning shell scripting basics, and you throw him IFS manipulation ^^ It's always good to know, but probably a bit too early for him... Or provide explanations such as IFS=+ means afterward the "$*" will expand to "all the arguments separated by a '+'", hence the $((computation)) will be replaced with the sum of all arguments

      – Olivier Dulac
      Nov 5 '13 at 10:13



















    clever. But I really hope you are not confusing him ^^ It seems he's learning shell scripting basics, and you throw him IFS manipulation ^^ It's always good to know, but probably a bit too early for him... Or provide explanations such as IFS=+ means afterward the "$*" will expand to "all the arguments separated by a '+'", hence the $((computation)) will be replaced with the sum of all arguments

    – Olivier Dulac
    Nov 5 '13 at 10:13







    clever. But I really hope you are not confusing him ^^ It seems he's learning shell scripting basics, and you throw him IFS manipulation ^^ It's always good to know, but probably a bit too early for him... Or provide explanations such as IFS=+ means afterward the "$*" will expand to "all the arguments separated by a '+'", hence the $((computation)) will be replaced with the sum of all arguments

    – Olivier Dulac
    Nov 5 '13 at 10:13















    8














    A non-looping variant:



    { printf %d+ "$@"; echo 0; } | bc


    Example



    Put the above in a script file, sum.



    #!/bin/bash

    { printf %d+ "$@"; echo 0; } | bc


    Run it like so:



    $ ./sum 4
    4
    $ ./sum 4 4 5
    13





    share|improve this answer






























      8














      A non-looping variant:



      { printf %d+ "$@"; echo 0; } | bc


      Example



      Put the above in a script file, sum.



      #!/bin/bash

      { printf %d+ "$@"; echo 0; } | bc


      Run it like so:



      $ ./sum 4
      4
      $ ./sum 4 4 5
      13





      share|improve this answer




























        8












        8








        8







        A non-looping variant:



        { printf %d+ "$@"; echo 0; } | bc


        Example



        Put the above in a script file, sum.



        #!/bin/bash

        { printf %d+ "$@"; echo 0; } | bc


        Run it like so:



        $ ./sum 4
        4
        $ ./sum 4 4 5
        13





        share|improve this answer















        A non-looping variant:



        { printf %d+ "$@"; echo 0; } | bc


        Example



        Put the above in a script file, sum.



        #!/bin/bash

        { printf %d+ "$@"; echo 0; } | bc


        Run it like so:



        $ ./sum 4
        4
        $ ./sum 4 4 5
        13






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 5 '13 at 8:25









        slm

        254k71535687




        254k71535687










        answered Nov 5 '13 at 7:25









        ricirici

        7,6072632




        7,6072632























            7














            You can use the following bash function:



            sum() {
            local sum=0
            for arg in "$@"; do
            (( sum += arg ))
            done
            echo $sum
            }





            share|improve this answer
























            • As a side question, is there a way to determine how many args are in the command line without looping?

              – John
              Nov 5 '13 at 7:13






            • 4





              $# is the number of args

              – rici
              Nov 5 '13 at 7:19











            • Thank you, perfect. One last question I forgot to clarify.. is there any way I can detect if it is like the very first argument? So say it is the very first argument, I can do something special with it. For example, as a random example, if the very first argument is a 7, I echo that the very first argument is a 7.

              – John
              Nov 5 '13 at 7:47






            • 2





              @John $1 is the first argument, $2 is the second argument, and so on. The variable $0 is the script's name. The total number of arguments is stored in $#. The variables $@ and $* return all the arguments. See also: how-to.wikia.com/wiki/…

              – Radu Rădeanu
              Nov 5 '13 at 8:04








            • 1





              @John typically if you want to process the first argument differently you first copy it to something else and then shift all the rest of the arguments with first=$1;shift

              – icarus
              Nov 19 '16 at 17:45
















            7














            You can use the following bash function:



            sum() {
            local sum=0
            for arg in "$@"; do
            (( sum += arg ))
            done
            echo $sum
            }





            share|improve this answer
























            • As a side question, is there a way to determine how many args are in the command line without looping?

              – John
              Nov 5 '13 at 7:13






            • 4





              $# is the number of args

              – rici
              Nov 5 '13 at 7:19











            • Thank you, perfect. One last question I forgot to clarify.. is there any way I can detect if it is like the very first argument? So say it is the very first argument, I can do something special with it. For example, as a random example, if the very first argument is a 7, I echo that the very first argument is a 7.

              – John
              Nov 5 '13 at 7:47






            • 2





              @John $1 is the first argument, $2 is the second argument, and so on. The variable $0 is the script's name. The total number of arguments is stored in $#. The variables $@ and $* return all the arguments. See also: how-to.wikia.com/wiki/…

              – Radu Rădeanu
              Nov 5 '13 at 8:04








            • 1





              @John typically if you want to process the first argument differently you first copy it to something else and then shift all the rest of the arguments with first=$1;shift

              – icarus
              Nov 19 '16 at 17:45














            7












            7








            7







            You can use the following bash function:



            sum() {
            local sum=0
            for arg in "$@"; do
            (( sum += arg ))
            done
            echo $sum
            }





            share|improve this answer













            You can use the following bash function:



            sum() {
            local sum=0
            for arg in "$@"; do
            (( sum += arg ))
            done
            echo $sum
            }






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 5 '13 at 6:46









            Radu RădeanuRadu Rădeanu

            1,04311239




            1,04311239













            • As a side question, is there a way to determine how many args are in the command line without looping?

              – John
              Nov 5 '13 at 7:13






            • 4





              $# is the number of args

              – rici
              Nov 5 '13 at 7:19











            • Thank you, perfect. One last question I forgot to clarify.. is there any way I can detect if it is like the very first argument? So say it is the very first argument, I can do something special with it. For example, as a random example, if the very first argument is a 7, I echo that the very first argument is a 7.

              – John
              Nov 5 '13 at 7:47






            • 2





              @John $1 is the first argument, $2 is the second argument, and so on. The variable $0 is the script's name. The total number of arguments is stored in $#. The variables $@ and $* return all the arguments. See also: how-to.wikia.com/wiki/…

              – Radu Rădeanu
              Nov 5 '13 at 8:04








            • 1





              @John typically if you want to process the first argument differently you first copy it to something else and then shift all the rest of the arguments with first=$1;shift

              – icarus
              Nov 19 '16 at 17:45



















            • As a side question, is there a way to determine how many args are in the command line without looping?

              – John
              Nov 5 '13 at 7:13






            • 4





              $# is the number of args

              – rici
              Nov 5 '13 at 7:19











            • Thank you, perfect. One last question I forgot to clarify.. is there any way I can detect if it is like the very first argument? So say it is the very first argument, I can do something special with it. For example, as a random example, if the very first argument is a 7, I echo that the very first argument is a 7.

              – John
              Nov 5 '13 at 7:47






            • 2





              @John $1 is the first argument, $2 is the second argument, and so on. The variable $0 is the script's name. The total number of arguments is stored in $#. The variables $@ and $* return all the arguments. See also: how-to.wikia.com/wiki/…

              – Radu Rădeanu
              Nov 5 '13 at 8:04








            • 1





              @John typically if you want to process the first argument differently you first copy it to something else and then shift all the rest of the arguments with first=$1;shift

              – icarus
              Nov 19 '16 at 17:45

















            As a side question, is there a way to determine how many args are in the command line without looping?

            – John
            Nov 5 '13 at 7:13





            As a side question, is there a way to determine how many args are in the command line without looping?

            – John
            Nov 5 '13 at 7:13




            4




            4





            $# is the number of args

            – rici
            Nov 5 '13 at 7:19





            $# is the number of args

            – rici
            Nov 5 '13 at 7:19













            Thank you, perfect. One last question I forgot to clarify.. is there any way I can detect if it is like the very first argument? So say it is the very first argument, I can do something special with it. For example, as a random example, if the very first argument is a 7, I echo that the very first argument is a 7.

            – John
            Nov 5 '13 at 7:47





            Thank you, perfect. One last question I forgot to clarify.. is there any way I can detect if it is like the very first argument? So say it is the very first argument, I can do something special with it. For example, as a random example, if the very first argument is a 7, I echo that the very first argument is a 7.

            – John
            Nov 5 '13 at 7:47




            2




            2





            @John $1 is the first argument, $2 is the second argument, and so on. The variable $0 is the script's name. The total number of arguments is stored in $#. The variables $@ and $* return all the arguments. See also: how-to.wikia.com/wiki/…

            – Radu Rădeanu
            Nov 5 '13 at 8:04







            @John $1 is the first argument, $2 is the second argument, and so on. The variable $0 is the script's name. The total number of arguments is stored in $#. The variables $@ and $* return all the arguments. See also: how-to.wikia.com/wiki/…

            – Radu Rădeanu
            Nov 5 '13 at 8:04






            1




            1





            @John typically if you want to process the first argument differently you first copy it to something else and then shift all the rest of the arguments with first=$1;shift

            – icarus
            Nov 19 '16 at 17:45





            @John typically if you want to process the first argument differently you first copy it to something else and then shift all the rest of the arguments with first=$1;shift

            – icarus
            Nov 19 '16 at 17:45


















            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%2f98907%2fhow-do-i-create-a-bash-script-that-sums-any-number-of-command-line-arguments%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

            Loup dans la culture

            How to solve the problem of ntp “Unable to contact time server” from KDE?

            Connection limited (no internet access)