I think your own solution using $ {OPT1 + -o "$ OPT1"} is good, and I donβt see any problems with this utility, but there is another approach using eval that no one has mentioned, which is even closer to your source code:
#!/bin/sh FILE1='some file' FILE2='another file' if [ somecriteria = true ]; then OPT1="-o '$FILE1'" fi if [ othercriteria = true ]; then OPT2="-p '$FILE2'" fi eval myutil "$OPT1" "$OPT2"
This will lead to what you want.
But you need to be careful if your file names contain single quotes as part of the literal file name string.
If you know exactly what your names look like when writing a script, just make sure that your literals with file names do not come out because you avoid placing the file name.
But this is even more important when you are processing user input or otherwise gaining access to the environment. - for example, if $ FILE1 is defined as abc'; /tmp/malicious_program ' abc'; /tmp/malicious_program ' and then you do eval, it will parse myutil string into:
myutil -o 'abc'; /tmp/malicious_program '' -p 'another file'
.. which is two separate commands and can be a massive security hole, depending on how exactly this script is executed relative to the object that created / tmp / malicious _program, and set $ FILE1.
In these cases, if you want to introduce a dependency on sed, you can do something like this in the first place:
FILE1=\'`printf %s "$FILE1" | sed "s/'/'\\\\''/g"`\'
.. this will lead to a good single-line shielded file name, while any quotation marks inside it will also be escaped.
Since in the Bourne / POSIX shell, nothing but a single quote can escape from the same line with quotation marks, so I use a single quote in my example. A double quote avoiding such things is possible, but your sed command should be much more complicated, as there are several other characters that you need to avoid inside double quotes (from my head: instead of just running away from quotes, you avoid double quotes , backslashes, backslashes, dollar signs, and possibly other things that I donβt think about).
PS: because I found that this "porting to the escaping shell and then eval later" is suitable in several cases, at least in one where it was absolutely necessary, I wrote a tiny C program (and an equivalent shell function using sed), which wraps all of its arguments in single shell caching, as described above, in case someone wants to use it instead of implementing their own: esceval