Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Given a program that requires some parameters, e.g. program -in file.in -out file.out, what would be the simple-most approach to write a bash script that could be called with or without any of these parameters and use default values for each?

script -in otherfile would run program -in otherfile -out file.out,
script -out otherout -furtherswitch would run program -in file.in -out otherout -furtherswitch etc.

share|improve this question
add comment

4 Answers

up vote 5 down vote accepted

A default value is easy to define in Bash:

foo="${bar-default}" # Sets foo to the value of $bar if defined, "default" otherwise
foo="${bar:-default}" # Sets foo to the value of $bar if defined or empty, "default" otherwise

To process your parameters, you can use a simple loop:

while true
do
    case "${1-}" in
        -in)
            infile="${2-}"
            shift 2
            ;;
        -out)
            outfile="${2-}"
            shift 2
            ;;
        *)
            break
            ;;
    esac
done

program -in "${infile-otherfile}" -out "${outfile-otherout}" "$@"

Useful reads:

I also recommend using getopt instead, because it is able to handle many special cases which would very quickly complicate and clutter your code (Non-trivial example).

share|improve this answer
    
Thanks! A while $# -gt 0 (or similar) and *) others="${others-} $1"; shift 1 ;; would survive other parameters before the default-able ones. But maybe I should learn getopt instead... –  Tobias Kienzler Feb 7 '13 at 11:12
    
Of course I could also simply write a python script... –  Tobias Kienzler Feb 7 '13 at 11:24
add comment
  • Pass all parameters ($*) passed to script to program too
  • Check each parameter you interested, if it's already in parameters passed, then ignore it. otherwise use default parameter value

Sample code

interested_parameter_names=(-in -out)
default_parameter_values=(file.in file.out)

program=echo
cmd="$program $*"

for ((index=0; index<${#interested_parameter_names[*]}; index++))
do
    param="${interested_parameter_names[$index]}"
    default_value="${default_parameter_values[$index]}"
    if [ "${*#*$param}" == "$*" ]   # if $* not contains $param
    then
        cmd="$cmd $param $default_value"
    fi
done

echo "command line will be:"
echo "$cmd"

echo
echo "execute result:"
$cmd

You can easily add more default parameters/values by add more array element in $interested_parameter_names and $default_parameter_values

Sample output

$ ./wrapper.sh -in non-default.txt -other-params
command line will be:
echo -in non-default.txt -other-params -out file.out

execute result:
-in non-default.txt -other-params -out file.out

Note

When passing parameters which contains space, it should be escaped by \, not just quoted them. Example:

./script -in new\ document.txt
share|improve this answer
    
Neat! I think the quotes issue can be solved by using $@ instead of $*. What does ${*#*$param} do? –  Tobias Kienzler Feb 7 '13 at 11:23
    
@TobiasKienzler, "${*#*$param}" == "$*" is used to check if $* NOT contains $param, it's Remove Smallest Prefix Pattern parameter expansion. –  LiuYan 刘研 Feb 7 '13 at 11:28
1  
./script -in new\ document.txt would not work, and there's not way to make it work with that flawed approach. By concatenating the arguments into a string, you're losing the information about how those arguments are separated. –  Stephane Chazelas Feb 7 '13 at 13:02
add comment

l0b0's answer shows how to set a default value through assignment and checking another variable's state (although, of course, you can also do this operating on the same variable you are assigning to), but there is a more concise way to do the same thing:

: "${foo=bar}" # $foo = bar if $foo is unset
: "${foo:=bar}" # $foo = bar if $foo is unset or empty
share|improve this answer
add comment

You have two ways, as usual, simple and hard. Simple is to use inner variables, for example

program -in otherfile -out file.out

Here variable are

$0 = The script name
$1 = -in
$2 = otherfile, etc.

The Hard way is to use getopt, more information you can find here.

share|improve this answer
    
Using $1 etc will fail if I omit parameters, and manually parsing them would be annoying. Is there no midway between that and getopt? –  Tobias Kienzler Feb 7 '13 at 10:23
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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