Expand glob with flag inserted before each filename
Using printf
and an xargs
supporting nul-delimited input:
printf -- '-f\0%s\0' important-files/*.txt | xargs -0 prog
printf
loops the format string over the arguments, so for each filename in the expansion of the glob, it will print -f
and the filename separated by the null character. xargs
then reads this and converts it into arguments for prog
. The --
needed since some implementations of printf
have trouble with a leading -
in the format string. Alternately, the -
can be replaced with \055
, which is standard.
Same principle as Rakesh's answer, but using the wildcard expansion directly.
With bash, try:
args=()
for f in important-files/*.txt
do
args+=(-f "$f")
done
prog "${args[@]}"
Note that this will work not merely with filenames that contain blanks but also with filenames that contain single or double quotes or even newlines.
Easy interactive use
For easy interactive use, define a function:
progf() { args=(); for f in "$@"; do args+=(-f "$f"); done; prog "${args[@]}"; }
This function can be used as follows:
progf important-files/*.txt
To make the function definition permanent, place it in your ~/.bashrc
file.
zsh
now has a P
glob qualifier for that.
For older versions, you can always use:
f=(*.txt)
prog -f$^f
$^f
enables the rcexpandparam
option for the expansion of $f
, where arrays are expanded in a style similar to that of the rc
shell.
In rc
(or zsh -o rcexpandparam
):
f=(*.txt)
prog -f$f
Is expanded to prog -fa.txt -fb.txt
, a bit as if you had written in csh (or other shells supporting brace expansion): prog -f{a.txt,b.txt}
.
(note that it's different from *.txt(P:-f:)
in that the file name is glued to the option -ffile.txt
as opposed to passing two arguments -f
file.txt
. Many commands including all those that use the standard getopt()
API to parse options support both ways passing arguments to options).
fish
also expands arrays like that:
set f *.txt
prog -f$f
In bash
, you can emulate it with:
f=(*.txt)
prog "${f[@]/#/-f}"
With ksh93
:
f=(*.txt)
prog "${f[@]/*/-f\0}"
For -f
and the corresponding file.txt
s to be passed as separate arguments, another option with zsh
using its array zipping operator:
o=-f f=(*.txt); prog ${o:^^f}
You could extend that for your -g
option. Assuming there's an even number of txt
files:
o=(-g '') f=(*.txt); prog ${o:^^f}
Would pass -g
options with two files at a time. Similar to what you'd get with:
printf -- '-g\0%s\0%s\0' *.txt | xargs -r0 prog