parsing a command option in a bash script
Clash 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!
bash shell-script options case
add a comment |Â
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!
bash shell-script options case
I just edited your question so that all the code was formatted correctly, but now it seems that there's a missingdone
somewhere in the script (for the firstfor
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
add a comment |Â
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!
bash shell-script options case
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!
bash shell-script options case
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 missingdone
somewhere in the script (for the firstfor
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
add a comment |Â
I just edited your question so that all the code was formatted correctly, but now it seems that there's a missingdone
somewhere in the script (for the firstfor
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
add a comment |Â
3 Answers
3
active
oldest
votes
up vote
0
down vote
One easy answer is twofold:
- Set a flag such as
send_email
totrue
, 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
add a comment |Â
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:
Your structure is fine. Parse the command option at the beginning of the script.
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 acase
statement with multiple possible options, place it in awhile
loop, in the formwhile "$1" ; do case ... esac; shift; done
. Theshift
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
.
add a comment |Â
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.
add a comment |Â
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
totrue
, 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
add a comment |Â
up vote
0
down vote
One easy answer is twofold:
- Set a flag such as
send_email
totrue
, 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
add a comment |Â
up vote
0
down vote
up vote
0
down vote
One easy answer is twofold:
- Set a flag such as
send_email
totrue
, 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
One easy answer is twofold:
- Set a flag such as
send_email
totrue
, 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
answered Mar 6 at 21:59
DopeGhoti
40.2k54779
40.2k54779
add a comment |Â
add a comment |Â
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:
Your structure is fine. Parse the command option at the beginning of the script.
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 acase
statement with multiple possible options, place it in awhile
loop, in the formwhile "$1" ; do case ... esac; shift; done
. Theshift
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
.
add a comment |Â
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:
Your structure is fine. Parse the command option at the beginning of the script.
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 acase
statement with multiple possible options, place it in awhile
loop, in the formwhile "$1" ; do case ... esac; shift; done
. Theshift
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
.
add a comment |Â
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:
Your structure is fine. Parse the command option at the beginning of the script.
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 acase
statement with multiple possible options, place it in awhile
loop, in the formwhile "$1" ; do case ... esac; shift; done
. Theshift
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
.
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:
Your structure is fine. Parse the command option at the beginning of the script.
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 acase
statement with multiple possible options, place it in awhile
loop, in the formwhile "$1" ; do case ... esac; shift; done
. Theshift
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
.
edited Mar 6 at 22:20
answered Mar 6 at 22:00
user1404316
2,314520
2,314520
add a comment |Â
add a comment |Â
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.
add a comment |Â
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.
add a comment |Â
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.
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.
answered Mar 7 at 3:55
cas
37.6k44392
37.6k44392
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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 firstfor
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