If your input options are positional (you know at which places they are), and not specified with flags, then what you want is just to build the command line. Just prepare the command arguments for all of them:
FLAG1="--flag1 $1"
FLAG2="--flag2 $2"
OPTFLAG1=""
OPTFLAG2=""
OPTFLAG3=""
if [ xFALSE != x"$3" ]; then
OPTFLAG1="--optflag1 $3"
fi
if [ xFALSE != x"$4" ]; then
OPTFLAG2="--optflag2 $4"
fi
#the same for other flags
#now just run the program
runprogram $FLAG1 $FLAG2 $OPTFLAG1 $OPTFLAG2 $OPTFLAG3
If the parameters are not specified, then the corresonding strings are empty and expand into nothing. Note that in the last line, there are no quotes. That's because you want the shell to split the parameters into words (to give --flag1
and $1
as separate arguments to your program). Of course, this will go wrong if your original parameters contain spaces. If you're the one running this, then you can leave it, but if that's a general script, it can have unexpected behaviour if the user inputs something with spaces. To handle that, you'll need to make the code a bit uglier.
The x
prefix in the []
test is there in case $3
or $4
is empty. In that case, bash would expand [ FALSE != $3 ]
into [ FALSE != ]
which is a syntax error, so another arbitrary character is there to guard against this. This is a very common way, you'll see it in many scripts.
I set OPTFLAG1
and the rest of them to ""
at the beginning just to be sure (in case they were set to something before), but if they weren't actually declared in the environment, then you don't strictly need to do that.
A couple of additional remarks:
- You could actually just receive the parameters the same way as
runprogram
does: with flags. That's what John N
is talking about. That's where getopts
becomes useful.
- Using FALSE for that purpose is a bit unstandard and quite long. Usually, one would use a single character (possibly
-
) to signal an empty value, or just pass an empty string, like ""
, if that's not otherwise a valid value of the parameter. Empty string also makes the test shorter, just use if [ -n "$3" ]
.
- If there is only one optional flag, or if they are dependent so you can never have OPTFLAG2, but not OPTFLAG1, then you can simply skip the ones you don't want to set. If you use
""
for empty parameters, like suggested above, you can skip all the trailing empties anyway.
This method is pretty much the way options are passed to compilers in Makefiles.
And again - if inputs may contain spaces, it gets ugly.
getopts
is what you want. Without that, you could use a loop with a switch statement to detect each flag, optional or not.getopts
, I would need to specify each argument combination? 3 & 4, 3 & 5, 3 & 4 & 5, etc. ?getopts
. Let's say I force users to run the script with all arguments:run_program.sh VAL VAL FALSE FALSE FALSE FALSE FALSE
which runs the program asprogram --flag1 VAL --flag2 VAL
. If you ranrun_program.sh VAL VAL FALSE 10 FALSE FALSE FALSE
, the program would run asprogram --flag1 VAL --flag2 VAL --optflag2 10
. How can you get such behavior withgetopts
?