Assume I have some utility that can take a number of options, each followed by a filename. E.g., I could call it as myutil
, myutil -o somefile
, myutil -p anotherfile
, myutil -o somefile -p anotherfile
, etc.... I want to write a wrapper POSIX shell script that is able to call myutil
with arbitrary combinations of options (depending on some conditions internal to the wrapper script, which aren't relevant to this question).
I thought of doing something like:
#!/bin/sh
file1=somefile
file2=anotherfile
if [ somecriteria = true ]; then
OPT1="-o $file1"
fi
if [ othercriteria = true ]; then
OPT2="-p $file2"
fi
myutil $OPT1 $OPT2
This works great—as long as neither filename has spaces: Assuming both if
s are true, myutil
gets $1 = [-o], $2 = [somefile], $3 = [-p], and $4 = [anotherfile]. However, if there are spaces, e.g., if file1="some file"
, $1 = [-o], $2 = [some], $3 = [file], etc. Of course, what I want is for $2 = [some file].
Putting another set of quotes around the filename in OPT1 and OPT2 doesn't help; e.g., if I change it to OPT1="-o \"$file1\""
, that just gets me $2 = ["some] and $3=[file"]. And putting in quotes around $OPT1 and $OPT2 in the call to myutil
doesn't work either: if I do that, $1 = [-o some file].
So, is there some trick to get this working, or some other approach that would do what I want? I'd like this to stick to standard shell features, so no bash-isms or ksh-isms, please :) See this for a description of what's in the standard.
After messing with it more, I found another approach that seems to do what I want:
#!/bin/sh
file1="some file"
file2=anotherfile
if [ somecriteria = true ]; then
OPT1="$file1"
fi
if [ othercriteria = true ]; then
OPT2="$file2"
fi
myutil ${OPT1:+-o "$OPT1"} ${OPT2:+-p "$OPT2"}
The construct ${parameter:+word} will be substituted with word if ${parameter} is set; if it's not set, it goes away. So if $OPT1
is unset, ${OPT1:+-o "$OPT1"}
disappears—notably, it doesn't turn into an empty string in argv
. If $OPT1
is set to some file
, the above expression is substituted with -o "some file"
, and myutil
gets $1 = [-o], $2 = [some file] as I want.
Note that myutil ${OPT1:+-o} "$OPT1" ${OPT2:+-p} "$OPT2"
does not do exactly what I want, because if $OPT1
is unset, the -o
goes away, but "$OPT1"
turns into an empty string—$1 = [], $2 = [-p], $3 = [anotherfile]
(Edited per Dennis's suggestion)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With