I know that, given l="a b c",
echo $l | xargs ls
yields
ls a b c
Which construct yields
mycommand -f a -f b -f c
I know that, given l="a b c",
echo $l | xargs ls
yields
ls a b c
Which construct yields
mycommand -f a -f b -f c
One way to do it:
echo "a b c" | xargs printf -- '-f %s\n' | xargs mycommand
This assumes a, b, and c don't contain blanks, newlines, quotes or backslashes. :)
With GNU findutil you can handle the general case, but it's slightly more complicated:
echo -n "a|b|c" | tr \| \\0 | xargs -0 printf -- '-f\0%s\0' | xargs -0 mycommand
You can replace the | separator with some other character, that doesn't appear in a, b, or c.
Edit: As @MichaelMol notes, with a very long list of arguments there is a risk of overflowing the maximum length of arguments that can be passed to mycommand. When that happens, the last xargs will split the list and run another copy of mycommand, and there is a risk of it leaving an unterminated -f. If you worry about that situation you could replace the last xargs -0 above by something like this:
... | xargs -x -0 mycommand
This won't solve the problem, but it would abort running mycommand when the list of arguments gets too long.
A better way to address it (IMO) would be:
in zsh:
l=(a b c)
mycommand -f$^l
or using array zipping so the argument be not attached to the option:
l=(a b c) o=(-f)
mycommand "${o:^^l}"
That way, it still works if the l array contains empty elements or elements containing spaces or any other problematic character for xargs. Example:
$ l=(a '' '"' 'x y' c) o=(-f)
$ printf '<%s>\n' "${o:^^l}"
<-f>
<a>
<-f>
<>
<-f>
<">
<-f>
<x y>
<-f>
<c>
in rc:
l=(a b c)
mycommand -f$l
in fish:
set l a b c
mycommand -f$l
(AFAIK, rc and fish have no array zipping)
With old-style Bourne-like shells like bash, you could always do (still allowing any character in the elements of the $@ array):
set -- a b c
for i do set -- "$@" -f "$i"; shift; done
mycommand "$@"
The simplest way to prefix arguments is via printf in conjunction with command substitution:
l="a b c"
mycommand $(printf ' -f %s' $l)
Alternatively, the command substitution $() can be rewritten by piping to xargs:
printf ' -f %s' $l | xargs mycommand
The command substitution allows to control location of the dynamic arguments in the argument list. For instance, you can prepend, append, or even place the arguments anywhere in between any other fixed arguments to be passed to mycommand.
The xargs approach works best to append arguments to the end, but it requires a more obscure syntax to handle different placement of dynamic arguments among fixed ones.
Here's my real-world example. It's a quick'n'dirty hack but it works.
docker-compose exec postfix mailq | egrep '^[A-Z0-9]{8}' | cut -f 1 -d " " | \
xargs printf -- '-d %s\n' | \
xargs -n4 -d '\n' echo "docker-compose exec -- postfix postsuper"
The above will generate this kind of output:
docker-compose exec -- postfix postsuper -d 794B95AB886 -d 7D2375AA207
docker-compose exec -- postfix postsuper -d 0A6AE5AA244 -d 048D85AA231
...
Prepend -f:
echo 'a b c' | xargs -n 1 echo -e -f | xargs mycommand
The -e argument is there to avoid -f being interpreted as another argument
If you instead want an output like this one (a, b, and c are each between an -f and a -g):
mycommand -f a -g -f b -g -f c -g
Then the command would be this one:
echo 'a b c' | tr ' ' '\n' | xargs -I @ echo -e -f @ -g | xargs mycommand