Reputation: 22225
I have a script P
which accepts file names as parameters:
P file1 file2 file3 ....
I also have a script G
which generates a (typically short list) of file names, one file name per line. In a master script which I would like to write in zsh, I want to use G
to generate the file names to be processed by P
. The naive attempt goes like this:
P $(G)
This works nearly well, only that I'm living in a world where malicious people enjoy creating files with embedded spaces. If G
would generate the list of files like this:
one_file
a file with spaces
P
would be called as
P one_file a file with spaces
instead of
P 'one_file' 'a file with spaces'
One obvious solution would be to glue G
and P
together not by command substitution, but by a small program in some language (Ruby, Perl, Python, Algol68,....), which does an exec of P
and passes the parameters to a read from stdin.
This would be trivial to write and could even be made reusable. However, I wonder, whether zsh with its grabbag of goodies would not have a solution for this problem builtin?
Upvotes: 5
Views: 2456
Reputation: 18329
This can be achieved with:
P ${(f)"$(G)"}
which will call P
as
P 'one_file' 'a file with spaces'
if the output of G
is
one_file
a file with spaces
Explanation:
The double quotes around $(G)
tell zsh to take the output of G
as one word (in the shell sense of the word word).
So just calling
P "$(G)"
would be equivaent of
P 'one_file
a file with spaces'
This is where the Parameter Expansion Flag f
comes into play. ${(f)SOMEVAR}
tells zsh to split $SOMEVAR
into words at newlines. Instead of a parameter (like SOMEVAR
) one can also use a command substitution (here $(G)
) inside ${...}
type parmeter expressions, which leads to the the command P ${(f)"$(G)"}
.
Upvotes: 5