2

I am trying to make a shell script which will ask some questions to the user, and will issue a final command with some or other options depending on what the user chose. Right now, the script looks like this:

if [[ $a == "y" ]] ; then

    command --option 1 argument

elif [[ $a == "n" ]] ; then

    command --option 2 argument

else

    command --option 3 argument

fi

Considering the command is very long, and contains a lot of options and arguments which remain constant between the different statements, I was wondering if I could in some way write a single line, with variable options being considered only if the corresponding condition is true.

This also applies to GNU parallel issuing one or more commands

if [[ $b == "n" ]] ; then

    find ./ -name '*.extension' | parallel -j $(nproc) command1 --option argument

else

    find ./ -name '*.extension' | parallel -j $(nproc) command1 --option argument\; command2 --option argument
  • FYI this looks like a good candidate for a case construct – steeldriver Sep 9 '16 at 0:43
  • -j $(nproc) is redundant: It has been the default for several years now. – Ole Tange Sep 9 '16 at 6:36
5

Sure, you can store the options to pass in a variable. Your first example could be something like this (also, [[ is a bash feature, not available in POSIX shell):

if [[ $a == "y" ]] ; then
    arg=1
elif [[ $a == "n" ]] ; then
    arg=2
else
    arg=3
fi

command --option "$arg" argument

Your second example:

if [[ $b != "n" ]] ; then
    extra="; command2 --option argument"
fi

find ./ -name '*.extension' | parallel -j $(nproc) command1 --option argument$extra
# if unset, $extra will be empty—you can of course explicitly
# set it to '' if this bothers you.

These work because of how variable expansion works: it's just substituted in to the command line, then (if unquoted) word-splitted, then passed to the command. So the called command doesn't know about the variables at all, the shell expanded them before calling it.

Since you're using bash, you can also use arrays:

args=()

if [ -n "$OPT_LONG" ]; then
    args+=(-l)
fi

if [ -n "$OPT_SORT_TIME" ]; then
    args+=(-t)
fi

ls "${args[@]}"

The array feature lets you easily build up arbitrarily long argument lists without worrying about word splitting breaking your code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.