parsing a command option in a bash script

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











up vote
0
down vote

favorite












I wrote I ‘quick’ script, and then thought of adding a “—nomail” option that would shut off my mail switch (of which the syntax is piped in from echo).



I thought this would be easy but I think, fundamentally, I did not structure the original script well so, this ‘option’ is killing me.



Very new to bash… THANKS!



MY WONDERFUL WORKING SCRIPT!:



 ## Current threshold value setting
THRESHOLD="80"

## Input Files and Mailx
LOCATIONS="fsIn.txt" ## Edit "fsIn.txt" to add or change filesystems
TOLIST="$(cat toList.txt | tr -s 'n' ' ' )" ## Sets who receives email if an error condition exists
REPLYTO="$(cat replyTo.txt | tr -s 'n' ' ' )" ## sets the reply to email addresses
FROM=”SCRIPT TEAM" ## Sets the "from" address on error emails
SUBJECT="$HOST: ! STORAGE LEVEL MET OR EXCEEDED !" ## Sets the subject line
############

for i in $(cat $LOCATIONS)

do

## Main df pipeline to return usage percentage
CAP=$(df -PH --no-sync "$i" | awk 'NR>1'| awk 'print $5' | sed 's/.$//')

for i in $(cat $LOCATIONS) #Several different file system locations are ‘catted’ in here . E.g. /dev

do

## Main df pipeline to return usage percentage to stdout and piped to mailx
CAP=$(df -PH --no-sync "$i" | awk 'NR>1'| awk 'print $5' | sed 's/.$//')
if [ $CAP -ge $THRESHOLD ]
then
(echo
echo "---------- CAPACITY TEST FAILED ---------- "
echo -n " SYSTEM NAME: " ; uname -n
echo -n " USER DETAIL: " ; whoami
echo " TEST AREA: $i "
echo " USED SPACE: $CAP% "
echo " THRESHOLD: $THRESHOLD% "
echo " !!!!!! THRESHOLD EXCEEDED !!!!!! ") | tee >(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
echo

else
echo
echo "++++++++++ CAPACITY TEST PASSED ++++++++++ "
echo " TEST AREA: $i "
echo " USED SPACE: $CAP% "
echo " THRESHOLD: $THRESHOLD% "
echo " !!! SUCCESS SUCCESS SUCCESS SUCCESS !!! "
echo
fi

done

exit 0



This works perfectly! But I haven’t a clue how to restructure this to include a –nomail option. It seems ‘case’ might be prudent but I am lost here.



Any thoughts?



Thanks so much!







share|improve this question






















  • I just edited your question so that all the code was formatted correctly, but now it seems that there's a missing done somewhere in the script (for the first for loop) - is your code one single script or are you showing two different alternative versions of the for loop?
    – cas
    Mar 7 at 3:11










  • Clean indentation makes code readable. What shall be affected by the -nomail option? Can't you show it on a smaller exampler? Which Interpreter is used, zsh, bash, ... - heterogenous?
    – user unknown
    Mar 7 at 4:51















up vote
0
down vote

favorite












I wrote I ‘quick’ script, and then thought of adding a “—nomail” option that would shut off my mail switch (of which the syntax is piped in from echo).



I thought this would be easy but I think, fundamentally, I did not structure the original script well so, this ‘option’ is killing me.



Very new to bash… THANKS!



MY WONDERFUL WORKING SCRIPT!:



 ## Current threshold value setting
THRESHOLD="80"

## Input Files and Mailx
LOCATIONS="fsIn.txt" ## Edit "fsIn.txt" to add or change filesystems
TOLIST="$(cat toList.txt | tr -s 'n' ' ' )" ## Sets who receives email if an error condition exists
REPLYTO="$(cat replyTo.txt | tr -s 'n' ' ' )" ## sets the reply to email addresses
FROM=”SCRIPT TEAM" ## Sets the "from" address on error emails
SUBJECT="$HOST: ! STORAGE LEVEL MET OR EXCEEDED !" ## Sets the subject line
############

for i in $(cat $LOCATIONS)

do

## Main df pipeline to return usage percentage
CAP=$(df -PH --no-sync "$i" | awk 'NR>1'| awk 'print $5' | sed 's/.$//')

for i in $(cat $LOCATIONS) #Several different file system locations are ‘catted’ in here . E.g. /dev

do

## Main df pipeline to return usage percentage to stdout and piped to mailx
CAP=$(df -PH --no-sync "$i" | awk 'NR>1'| awk 'print $5' | sed 's/.$//')
if [ $CAP -ge $THRESHOLD ]
then
(echo
echo "---------- CAPACITY TEST FAILED ---------- "
echo -n " SYSTEM NAME: " ; uname -n
echo -n " USER DETAIL: " ; whoami
echo " TEST AREA: $i "
echo " USED SPACE: $CAP% "
echo " THRESHOLD: $THRESHOLD% "
echo " !!!!!! THRESHOLD EXCEEDED !!!!!! ") | tee >(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
echo

else
echo
echo "++++++++++ CAPACITY TEST PASSED ++++++++++ "
echo " TEST AREA: $i "
echo " USED SPACE: $CAP% "
echo " THRESHOLD: $THRESHOLD% "
echo " !!! SUCCESS SUCCESS SUCCESS SUCCESS !!! "
echo
fi

done

exit 0



This works perfectly! But I haven’t a clue how to restructure this to include a –nomail option. It seems ‘case’ might be prudent but I am lost here.



Any thoughts?



Thanks so much!







share|improve this question






















  • I just edited your question so that all the code was formatted correctly, but now it seems that there's a missing done somewhere in the script (for the first for loop) - is your code one single script or are you showing two different alternative versions of the for loop?
    – cas
    Mar 7 at 3:11










  • Clean indentation makes code readable. What shall be affected by the -nomail option? Can't you show it on a smaller exampler? Which Interpreter is used, zsh, bash, ... - heterogenous?
    – user unknown
    Mar 7 at 4:51













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I wrote I ‘quick’ script, and then thought of adding a “—nomail” option that would shut off my mail switch (of which the syntax is piped in from echo).



I thought this would be easy but I think, fundamentally, I did not structure the original script well so, this ‘option’ is killing me.



Very new to bash… THANKS!



MY WONDERFUL WORKING SCRIPT!:



 ## Current threshold value setting
THRESHOLD="80"

## Input Files and Mailx
LOCATIONS="fsIn.txt" ## Edit "fsIn.txt" to add or change filesystems
TOLIST="$(cat toList.txt | tr -s 'n' ' ' )" ## Sets who receives email if an error condition exists
REPLYTO="$(cat replyTo.txt | tr -s 'n' ' ' )" ## sets the reply to email addresses
FROM=”SCRIPT TEAM" ## Sets the "from" address on error emails
SUBJECT="$HOST: ! STORAGE LEVEL MET OR EXCEEDED !" ## Sets the subject line
############

for i in $(cat $LOCATIONS)

do

## Main df pipeline to return usage percentage
CAP=$(df -PH --no-sync "$i" | awk 'NR>1'| awk 'print $5' | sed 's/.$//')

for i in $(cat $LOCATIONS) #Several different file system locations are ‘catted’ in here . E.g. /dev

do

## Main df pipeline to return usage percentage to stdout and piped to mailx
CAP=$(df -PH --no-sync "$i" | awk 'NR>1'| awk 'print $5' | sed 's/.$//')
if [ $CAP -ge $THRESHOLD ]
then
(echo
echo "---------- CAPACITY TEST FAILED ---------- "
echo -n " SYSTEM NAME: " ; uname -n
echo -n " USER DETAIL: " ; whoami
echo " TEST AREA: $i "
echo " USED SPACE: $CAP% "
echo " THRESHOLD: $THRESHOLD% "
echo " !!!!!! THRESHOLD EXCEEDED !!!!!! ") | tee >(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
echo

else
echo
echo "++++++++++ CAPACITY TEST PASSED ++++++++++ "
echo " TEST AREA: $i "
echo " USED SPACE: $CAP% "
echo " THRESHOLD: $THRESHOLD% "
echo " !!! SUCCESS SUCCESS SUCCESS SUCCESS !!! "
echo
fi

done

exit 0



This works perfectly! But I haven’t a clue how to restructure this to include a –nomail option. It seems ‘case’ might be prudent but I am lost here.



Any thoughts?



Thanks so much!







share|improve this question














I wrote I ‘quick’ script, and then thought of adding a “—nomail” option that would shut off my mail switch (of which the syntax is piped in from echo).



I thought this would be easy but I think, fundamentally, I did not structure the original script well so, this ‘option’ is killing me.



Very new to bash… THANKS!



MY WONDERFUL WORKING SCRIPT!:



 ## Current threshold value setting
THRESHOLD="80"

## Input Files and Mailx
LOCATIONS="fsIn.txt" ## Edit "fsIn.txt" to add or change filesystems
TOLIST="$(cat toList.txt | tr -s 'n' ' ' )" ## Sets who receives email if an error condition exists
REPLYTO="$(cat replyTo.txt | tr -s 'n' ' ' )" ## sets the reply to email addresses
FROM=”SCRIPT TEAM" ## Sets the "from" address on error emails
SUBJECT="$HOST: ! STORAGE LEVEL MET OR EXCEEDED !" ## Sets the subject line
############

for i in $(cat $LOCATIONS)

do

## Main df pipeline to return usage percentage
CAP=$(df -PH --no-sync "$i" | awk 'NR>1'| awk 'print $5' | sed 's/.$//')

for i in $(cat $LOCATIONS) #Several different file system locations are ‘catted’ in here . E.g. /dev

do

## Main df pipeline to return usage percentage to stdout and piped to mailx
CAP=$(df -PH --no-sync "$i" | awk 'NR>1'| awk 'print $5' | sed 's/.$//')
if [ $CAP -ge $THRESHOLD ]
then
(echo
echo "---------- CAPACITY TEST FAILED ---------- "
echo -n " SYSTEM NAME: " ; uname -n
echo -n " USER DETAIL: " ; whoami
echo " TEST AREA: $i "
echo " USED SPACE: $CAP% "
echo " THRESHOLD: $THRESHOLD% "
echo " !!!!!! THRESHOLD EXCEEDED !!!!!! ") | tee >(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
echo

else
echo
echo "++++++++++ CAPACITY TEST PASSED ++++++++++ "
echo " TEST AREA: $i "
echo " USED SPACE: $CAP% "
echo " THRESHOLD: $THRESHOLD% "
echo " !!! SUCCESS SUCCESS SUCCESS SUCCESS !!! "
echo
fi

done

exit 0



This works perfectly! But I haven’t a clue how to restructure this to include a –nomail option. It seems ‘case’ might be prudent but I am lost here.



Any thoughts?



Thanks so much!









share|improve this question













share|improve this question




share|improve this question








edited Mar 7 at 6:17









user1404316

2,314520




2,314520










asked Mar 6 at 21:47









SSDdude

616




616











  • I just edited your question so that all the code was formatted correctly, but now it seems that there's a missing done somewhere in the script (for the first for loop) - is your code one single script or are you showing two different alternative versions of the for loop?
    – cas
    Mar 7 at 3:11










  • Clean indentation makes code readable. What shall be affected by the -nomail option? Can't you show it on a smaller exampler? Which Interpreter is used, zsh, bash, ... - heterogenous?
    – user unknown
    Mar 7 at 4:51

















  • I just edited your question so that all the code was formatted correctly, but now it seems that there's a missing done somewhere in the script (for the first for loop) - is your code one single script or are you showing two different alternative versions of the for loop?
    – cas
    Mar 7 at 3:11










  • Clean indentation makes code readable. What shall be affected by the -nomail option? Can't you show it on a smaller exampler? Which Interpreter is used, zsh, bash, ... - heterogenous?
    – user unknown
    Mar 7 at 4:51
















I just edited your question so that all the code was formatted correctly, but now it seems that there's a missing done somewhere in the script (for the first for loop) - is your code one single script or are you showing two different alternative versions of the for loop?
– cas
Mar 7 at 3:11




I just edited your question so that all the code was formatted correctly, but now it seems that there's a missing done somewhere in the script (for the first for loop) - is your code one single script or are you showing two different alternative versions of the for loop?
– cas
Mar 7 at 3:11












Clean indentation makes code readable. What shall be affected by the -nomail option? Can't you show it on a smaller exampler? Which Interpreter is used, zsh, bash, ... - heterogenous?
– user unknown
Mar 7 at 4:51





Clean indentation makes code readable. What shall be affected by the -nomail option? Can't you show it on a smaller exampler? Which Interpreter is used, zsh, bash, ... - heterogenous?
– user unknown
Mar 7 at 4:51











3 Answers
3






active

oldest

votes

















up vote
0
down vote













One easy answer is twofold:



  • Set a flag such as send_email to true, and either unset it or set it to false if your email suppressing argument is present.

  • Compose your email in advance by assembling a variable or temporary file which would be the output, and then punting the actual sending of mail to a function call:

For example:



send_email="true"
handle_email() mailx -s "$subject" -r "$from" -S replyto="$replyto" $recipients[@]


[...]
if [[ "--nomail" == "$1" ]]; then
send_email=false
fi
[...]
if [[ true == "$send_email ]]; then
handle_email
fi





share|improve this answer



























    up vote
    0
    down vote













    Update



    I went back and read your entire question and realized that I had originally answered a question slightly different than the one you asked, so here goes:



    1. Your structure is fine. Parse the command option at the beginning of the script.


    2. Yes, you can use a case statement, checking against $1 (see my original answer below), although if you are only planning a single option, you can just as easily perform a single test (see my original answer below). To use a case statement with multiple possible options, place it in a while loop, in the form while "$1" ; do case ... esac; shift; done. The shift command will replace $1 with the next word / option from your command line.


    Original answer



    There are several ways of dealing with this. If this is the only option, or if there are only a few, you may consider parsing it manually yourself. In shell-speak, all words after the shell command are called parameters, and each is assigned to a positional parameter, in the form $n with n starting at 1. Thus, you can perform a test to check whether [[ $1 == "--nomail" ]] and act accordingly. That's the simple straightforward way for only a single option.



    For more complex shell scripts with many options, you may want to avail yourself of some form of getopts command to parse the options for you. The bash shell includes a version of getopts as a builtin, and you can learn more about it by typing man bash at the command line and then (if your default pager is set to less) /^ *getopt.






    share|improve this answer





























      up vote
      0
      down vote













      Other answers have already mentioned how to take a command-line option (i.e. checking "$1" directly or using getopts). My answer is on how to quickly modify your script to make use of a --nomail option without having to rewrite your script from scratch. In the long run, you should probably do that, if only to take advantage of the gradual improvements in your shell-scripting skill and knowledge.



      The obvious way is to use a variable or a temporary file to store the output you want to either print or print & mail, and then choose what to do with it on each occasion.



      The less obvious way is to replace the pipe to tee >(mailx ...) with a pipe to a function call that makes the decision to either tee its stdin to mailx or just cat it. With this method, there's no need to store the output, just pipe it and let the function deal with it - the rest of your code doesn't need to know or care (and, most importantly, doesn't need to be written to handle both cases).



      Here's how...



      First, add code like this somewhere near the start of your script:



      # set the default, i.e. to send mail.
      send_email=1

      # Very basic option processing. Using getopts would be better.
      [ "$1" == "--nomail" ] && send_email=''

      myoutput()
      if [ "$send_email" ] ; then
      # print stdin to stdout AND mail it
      tee <(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
      else
      # only print stdin to stdout. no mail.
      cat
      fi



      Second, use the function defined here by replacing the | tee ... in your for loop with | myoutput.



      (myoutput is a lame name for a function. rename it to cat_or_mail or whatever makes most sense to you)



      Ideally, the function should take arguments rather than relying on global variables, and should be written something like this:



      myoutput() 
      local send_email SUBJECT FROM REPYLTO TOLIST

      # more of the primitive option handling. getopts can and should be used
      # inside a function too.
      send_email="$1"
      SUBJECT="$2"
      FROM="$3"
      REPLYTO="$4"
      TOLIST="$5"

      # add code here to check if those variables contain valid values.
      # print warnings and/or abort and/or set appropriate defaults if they don't.

      if [ "$send_email" ] ; then
      # print stdin to stdout AND mail it
      tee <(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
      else
      # only print stdin to stdout. no mail.
      cat
      fi



      and call it as ... | myoutput "$send_email" "$SUBJECT" "$FROM" "$REPLYTO" "$TOLIST"



      This makes the function re-usable without having to set global variables beforehand - just call it with the values you need.






      share|improve this answer




















        Your Answer







        StackExchange.ready(function()
        var channelOptions =
        tags: "".split(" "),
        id: "106"
        ;
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function()
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled)
        StackExchange.using("snippets", function()
        createEditor();
        );

        else
        createEditor();

        );

        function createEditor()
        StackExchange.prepareEditor(
        heartbeatType: 'answer',
        convertImagesToLinks: false,
        noModals: false,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: null,
        bindNavPrevention: true,
        postfix: "",
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        );



        );








         

        draft saved


        draft discarded


















        StackExchange.ready(
        function ()
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f428620%2fparsing-a-command-option-in-a-bash-script%23new-answer', 'question_page');

        );

        Post as a guest






























        3 Answers
        3






        active

        oldest

        votes








        3 Answers
        3






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes








        up vote
        0
        down vote













        One easy answer is twofold:



        • Set a flag such as send_email to true, and either unset it or set it to false if your email suppressing argument is present.

        • Compose your email in advance by assembling a variable or temporary file which would be the output, and then punting the actual sending of mail to a function call:

        For example:



        send_email="true"
        handle_email() mailx -s "$subject" -r "$from" -S replyto="$replyto" $recipients[@]


        [...]
        if [[ "--nomail" == "$1" ]]; then
        send_email=false
        fi
        [...]
        if [[ true == "$send_email ]]; then
        handle_email
        fi





        share|improve this answer
























          up vote
          0
          down vote













          One easy answer is twofold:



          • Set a flag such as send_email to true, and either unset it or set it to false if your email suppressing argument is present.

          • Compose your email in advance by assembling a variable or temporary file which would be the output, and then punting the actual sending of mail to a function call:

          For example:



          send_email="true"
          handle_email() mailx -s "$subject" -r "$from" -S replyto="$replyto" $recipients[@]


          [...]
          if [[ "--nomail" == "$1" ]]; then
          send_email=false
          fi
          [...]
          if [[ true == "$send_email ]]; then
          handle_email
          fi





          share|improve this answer






















            up vote
            0
            down vote










            up vote
            0
            down vote









            One easy answer is twofold:



            • Set a flag such as send_email to true, and either unset it or set it to false if your email suppressing argument is present.

            • Compose your email in advance by assembling a variable or temporary file which would be the output, and then punting the actual sending of mail to a function call:

            For example:



            send_email="true"
            handle_email() mailx -s "$subject" -r "$from" -S replyto="$replyto" $recipients[@]


            [...]
            if [[ "--nomail" == "$1" ]]; then
            send_email=false
            fi
            [...]
            if [[ true == "$send_email ]]; then
            handle_email
            fi





            share|improve this answer












            One easy answer is twofold:



            • Set a flag such as send_email to true, and either unset it or set it to false if your email suppressing argument is present.

            • Compose your email in advance by assembling a variable or temporary file which would be the output, and then punting the actual sending of mail to a function call:

            For example:



            send_email="true"
            handle_email() mailx -s "$subject" -r "$from" -S replyto="$replyto" $recipients[@]


            [...]
            if [[ "--nomail" == "$1" ]]; then
            send_email=false
            fi
            [...]
            if [[ true == "$send_email ]]; then
            handle_email
            fi






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Mar 6 at 21:59









            DopeGhoti

            40.2k54779




            40.2k54779






















                up vote
                0
                down vote













                Update



                I went back and read your entire question and realized that I had originally answered a question slightly different than the one you asked, so here goes:



                1. Your structure is fine. Parse the command option at the beginning of the script.


                2. Yes, you can use a case statement, checking against $1 (see my original answer below), although if you are only planning a single option, you can just as easily perform a single test (see my original answer below). To use a case statement with multiple possible options, place it in a while loop, in the form while "$1" ; do case ... esac; shift; done. The shift command will replace $1 with the next word / option from your command line.


                Original answer



                There are several ways of dealing with this. If this is the only option, or if there are only a few, you may consider parsing it manually yourself. In shell-speak, all words after the shell command are called parameters, and each is assigned to a positional parameter, in the form $n with n starting at 1. Thus, you can perform a test to check whether [[ $1 == "--nomail" ]] and act accordingly. That's the simple straightforward way for only a single option.



                For more complex shell scripts with many options, you may want to avail yourself of some form of getopts command to parse the options for you. The bash shell includes a version of getopts as a builtin, and you can learn more about it by typing man bash at the command line and then (if your default pager is set to less) /^ *getopt.






                share|improve this answer


























                  up vote
                  0
                  down vote













                  Update



                  I went back and read your entire question and realized that I had originally answered a question slightly different than the one you asked, so here goes:



                  1. Your structure is fine. Parse the command option at the beginning of the script.


                  2. Yes, you can use a case statement, checking against $1 (see my original answer below), although if you are only planning a single option, you can just as easily perform a single test (see my original answer below). To use a case statement with multiple possible options, place it in a while loop, in the form while "$1" ; do case ... esac; shift; done. The shift command will replace $1 with the next word / option from your command line.


                  Original answer



                  There are several ways of dealing with this. If this is the only option, or if there are only a few, you may consider parsing it manually yourself. In shell-speak, all words after the shell command are called parameters, and each is assigned to a positional parameter, in the form $n with n starting at 1. Thus, you can perform a test to check whether [[ $1 == "--nomail" ]] and act accordingly. That's the simple straightforward way for only a single option.



                  For more complex shell scripts with many options, you may want to avail yourself of some form of getopts command to parse the options for you. The bash shell includes a version of getopts as a builtin, and you can learn more about it by typing man bash at the command line and then (if your default pager is set to less) /^ *getopt.






                  share|improve this answer
























                    up vote
                    0
                    down vote










                    up vote
                    0
                    down vote









                    Update



                    I went back and read your entire question and realized that I had originally answered a question slightly different than the one you asked, so here goes:



                    1. Your structure is fine. Parse the command option at the beginning of the script.


                    2. Yes, you can use a case statement, checking against $1 (see my original answer below), although if you are only planning a single option, you can just as easily perform a single test (see my original answer below). To use a case statement with multiple possible options, place it in a while loop, in the form while "$1" ; do case ... esac; shift; done. The shift command will replace $1 with the next word / option from your command line.


                    Original answer



                    There are several ways of dealing with this. If this is the only option, or if there are only a few, you may consider parsing it manually yourself. In shell-speak, all words after the shell command are called parameters, and each is assigned to a positional parameter, in the form $n with n starting at 1. Thus, you can perform a test to check whether [[ $1 == "--nomail" ]] and act accordingly. That's the simple straightforward way for only a single option.



                    For more complex shell scripts with many options, you may want to avail yourself of some form of getopts command to parse the options for you. The bash shell includes a version of getopts as a builtin, and you can learn more about it by typing man bash at the command line and then (if your default pager is set to less) /^ *getopt.






                    share|improve this answer














                    Update



                    I went back and read your entire question and realized that I had originally answered a question slightly different than the one you asked, so here goes:



                    1. Your structure is fine. Parse the command option at the beginning of the script.


                    2. Yes, you can use a case statement, checking against $1 (see my original answer below), although if you are only planning a single option, you can just as easily perform a single test (see my original answer below). To use a case statement with multiple possible options, place it in a while loop, in the form while "$1" ; do case ... esac; shift; done. The shift command will replace $1 with the next word / option from your command line.


                    Original answer



                    There are several ways of dealing with this. If this is the only option, or if there are only a few, you may consider parsing it manually yourself. In shell-speak, all words after the shell command are called parameters, and each is assigned to a positional parameter, in the form $n with n starting at 1. Thus, you can perform a test to check whether [[ $1 == "--nomail" ]] and act accordingly. That's the simple straightforward way for only a single option.



                    For more complex shell scripts with many options, you may want to avail yourself of some form of getopts command to parse the options for you. The bash shell includes a version of getopts as a builtin, and you can learn more about it by typing man bash at the command line and then (if your default pager is set to less) /^ *getopt.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Mar 6 at 22:20

























                    answered Mar 6 at 22:00









                    user1404316

                    2,314520




                    2,314520




















                        up vote
                        0
                        down vote













                        Other answers have already mentioned how to take a command-line option (i.e. checking "$1" directly or using getopts). My answer is on how to quickly modify your script to make use of a --nomail option without having to rewrite your script from scratch. In the long run, you should probably do that, if only to take advantage of the gradual improvements in your shell-scripting skill and knowledge.



                        The obvious way is to use a variable or a temporary file to store the output you want to either print or print & mail, and then choose what to do with it on each occasion.



                        The less obvious way is to replace the pipe to tee >(mailx ...) with a pipe to a function call that makes the decision to either tee its stdin to mailx or just cat it. With this method, there's no need to store the output, just pipe it and let the function deal with it - the rest of your code doesn't need to know or care (and, most importantly, doesn't need to be written to handle both cases).



                        Here's how...



                        First, add code like this somewhere near the start of your script:



                        # set the default, i.e. to send mail.
                        send_email=1

                        # Very basic option processing. Using getopts would be better.
                        [ "$1" == "--nomail" ] && send_email=''

                        myoutput()
                        if [ "$send_email" ] ; then
                        # print stdin to stdout AND mail it
                        tee <(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
                        else
                        # only print stdin to stdout. no mail.
                        cat
                        fi



                        Second, use the function defined here by replacing the | tee ... in your for loop with | myoutput.



                        (myoutput is a lame name for a function. rename it to cat_or_mail or whatever makes most sense to you)



                        Ideally, the function should take arguments rather than relying on global variables, and should be written something like this:



                        myoutput() 
                        local send_email SUBJECT FROM REPYLTO TOLIST

                        # more of the primitive option handling. getopts can and should be used
                        # inside a function too.
                        send_email="$1"
                        SUBJECT="$2"
                        FROM="$3"
                        REPLYTO="$4"
                        TOLIST="$5"

                        # add code here to check if those variables contain valid values.
                        # print warnings and/or abort and/or set appropriate defaults if they don't.

                        if [ "$send_email" ] ; then
                        # print stdin to stdout AND mail it
                        tee <(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
                        else
                        # only print stdin to stdout. no mail.
                        cat
                        fi



                        and call it as ... | myoutput "$send_email" "$SUBJECT" "$FROM" "$REPLYTO" "$TOLIST"



                        This makes the function re-usable without having to set global variables beforehand - just call it with the values you need.






                        share|improve this answer
























                          up vote
                          0
                          down vote













                          Other answers have already mentioned how to take a command-line option (i.e. checking "$1" directly or using getopts). My answer is on how to quickly modify your script to make use of a --nomail option without having to rewrite your script from scratch. In the long run, you should probably do that, if only to take advantage of the gradual improvements in your shell-scripting skill and knowledge.



                          The obvious way is to use a variable or a temporary file to store the output you want to either print or print & mail, and then choose what to do with it on each occasion.



                          The less obvious way is to replace the pipe to tee >(mailx ...) with a pipe to a function call that makes the decision to either tee its stdin to mailx or just cat it. With this method, there's no need to store the output, just pipe it and let the function deal with it - the rest of your code doesn't need to know or care (and, most importantly, doesn't need to be written to handle both cases).



                          Here's how...



                          First, add code like this somewhere near the start of your script:



                          # set the default, i.e. to send mail.
                          send_email=1

                          # Very basic option processing. Using getopts would be better.
                          [ "$1" == "--nomail" ] && send_email=''

                          myoutput()
                          if [ "$send_email" ] ; then
                          # print stdin to stdout AND mail it
                          tee <(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
                          else
                          # only print stdin to stdout. no mail.
                          cat
                          fi



                          Second, use the function defined here by replacing the | tee ... in your for loop with | myoutput.



                          (myoutput is a lame name for a function. rename it to cat_or_mail or whatever makes most sense to you)



                          Ideally, the function should take arguments rather than relying on global variables, and should be written something like this:



                          myoutput() 
                          local send_email SUBJECT FROM REPYLTO TOLIST

                          # more of the primitive option handling. getopts can and should be used
                          # inside a function too.
                          send_email="$1"
                          SUBJECT="$2"
                          FROM="$3"
                          REPLYTO="$4"
                          TOLIST="$5"

                          # add code here to check if those variables contain valid values.
                          # print warnings and/or abort and/or set appropriate defaults if they don't.

                          if [ "$send_email" ] ; then
                          # print stdin to stdout AND mail it
                          tee <(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
                          else
                          # only print stdin to stdout. no mail.
                          cat
                          fi



                          and call it as ... | myoutput "$send_email" "$SUBJECT" "$FROM" "$REPLYTO" "$TOLIST"



                          This makes the function re-usable without having to set global variables beforehand - just call it with the values you need.






                          share|improve this answer






















                            up vote
                            0
                            down vote










                            up vote
                            0
                            down vote









                            Other answers have already mentioned how to take a command-line option (i.e. checking "$1" directly or using getopts). My answer is on how to quickly modify your script to make use of a --nomail option without having to rewrite your script from scratch. In the long run, you should probably do that, if only to take advantage of the gradual improvements in your shell-scripting skill and knowledge.



                            The obvious way is to use a variable or a temporary file to store the output you want to either print or print & mail, and then choose what to do with it on each occasion.



                            The less obvious way is to replace the pipe to tee >(mailx ...) with a pipe to a function call that makes the decision to either tee its stdin to mailx or just cat it. With this method, there's no need to store the output, just pipe it and let the function deal with it - the rest of your code doesn't need to know or care (and, most importantly, doesn't need to be written to handle both cases).



                            Here's how...



                            First, add code like this somewhere near the start of your script:



                            # set the default, i.e. to send mail.
                            send_email=1

                            # Very basic option processing. Using getopts would be better.
                            [ "$1" == "--nomail" ] && send_email=''

                            myoutput()
                            if [ "$send_email" ] ; then
                            # print stdin to stdout AND mail it
                            tee <(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
                            else
                            # only print stdin to stdout. no mail.
                            cat
                            fi



                            Second, use the function defined here by replacing the | tee ... in your for loop with | myoutput.



                            (myoutput is a lame name for a function. rename it to cat_or_mail or whatever makes most sense to you)



                            Ideally, the function should take arguments rather than relying on global variables, and should be written something like this:



                            myoutput() 
                            local send_email SUBJECT FROM REPYLTO TOLIST

                            # more of the primitive option handling. getopts can and should be used
                            # inside a function too.
                            send_email="$1"
                            SUBJECT="$2"
                            FROM="$3"
                            REPLYTO="$4"
                            TOLIST="$5"

                            # add code here to check if those variables contain valid values.
                            # print warnings and/or abort and/or set appropriate defaults if they don't.

                            if [ "$send_email" ] ; then
                            # print stdin to stdout AND mail it
                            tee <(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
                            else
                            # only print stdin to stdout. no mail.
                            cat
                            fi



                            and call it as ... | myoutput "$send_email" "$SUBJECT" "$FROM" "$REPLYTO" "$TOLIST"



                            This makes the function re-usable without having to set global variables beforehand - just call it with the values you need.






                            share|improve this answer












                            Other answers have already mentioned how to take a command-line option (i.e. checking "$1" directly or using getopts). My answer is on how to quickly modify your script to make use of a --nomail option without having to rewrite your script from scratch. In the long run, you should probably do that, if only to take advantage of the gradual improvements in your shell-scripting skill and knowledge.



                            The obvious way is to use a variable or a temporary file to store the output you want to either print or print & mail, and then choose what to do with it on each occasion.



                            The less obvious way is to replace the pipe to tee >(mailx ...) with a pipe to a function call that makes the decision to either tee its stdin to mailx or just cat it. With this method, there's no need to store the output, just pipe it and let the function deal with it - the rest of your code doesn't need to know or care (and, most importantly, doesn't need to be written to handle both cases).



                            Here's how...



                            First, add code like this somewhere near the start of your script:



                            # set the default, i.e. to send mail.
                            send_email=1

                            # Very basic option processing. Using getopts would be better.
                            [ "$1" == "--nomail" ] && send_email=''

                            myoutput()
                            if [ "$send_email" ] ; then
                            # print stdin to stdout AND mail it
                            tee <(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
                            else
                            # only print stdin to stdout. no mail.
                            cat
                            fi



                            Second, use the function defined here by replacing the | tee ... in your for loop with | myoutput.



                            (myoutput is a lame name for a function. rename it to cat_or_mail or whatever makes most sense to you)



                            Ideally, the function should take arguments rather than relying on global variables, and should be written something like this:



                            myoutput() 
                            local send_email SUBJECT FROM REPYLTO TOLIST

                            # more of the primitive option handling. getopts can and should be used
                            # inside a function too.
                            send_email="$1"
                            SUBJECT="$2"
                            FROM="$3"
                            REPLYTO="$4"
                            TOLIST="$5"

                            # add code here to check if those variables contain valid values.
                            # print warnings and/or abort and/or set appropriate defaults if they don't.

                            if [ "$send_email" ] ; then
                            # print stdin to stdout AND mail it
                            tee <(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
                            else
                            # only print stdin to stdout. no mail.
                            cat
                            fi



                            and call it as ... | myoutput "$send_email" "$SUBJECT" "$FROM" "$REPLYTO" "$TOLIST"



                            This makes the function re-usable without having to set global variables beforehand - just call it with the values you need.







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Mar 7 at 3:55









                            cas

                            37.6k44392




                            37.6k44392






















                                 

                                draft saved


                                draft discarded


























                                 


                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function ()
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f428620%2fparsing-a-command-option-in-a-bash-script%23new-answer', 'question_page');

                                );

                                Post as a guest













































































                                Popular posts from this blog

                                How to check contact read email or not when send email to Individual?

                                Bahrain

                                Postfix configuration issue with fips on centos 7; mailgun relay