Variable expansion is different in zsh from that in bash
The following is a simple test case for what I want to illustrate.
In bash,
# define the function f
f () { ls $args; }
# Runs the command `ls`
f
# Runs the fommand `ls -a`
args="-a"
f
# Runs the command `ls -a -l`
args="-a -l"
f
But in zsh
# define the function f
f () { ls $args }
# Runs the command `ls`
f
# Runs the fommand `ls -a`
args="-a"
f
# I expect it to run `ls -a -l`, instead it gives me an error
args="-a -l"
f
The last line in the zsh on above, gives me the following error
ls: invalid option -- ' '
Try `ls --help' for more information.
I think zsh is executing
ls "-a -l"
which is when I get the same error. So, how do I get bash's behavior here?
I'm not sure if I'm clear, let me know if there is something you want to know.
Solution 1:
The difference is that (by default) zsh does not do word splitting for unquoted parameter expansions.
You can enable “normal” word splitting by setting the SH_WORD_SPLIT option or by using the =
flag on an individual expansion:
ls ${=args}
or
setopt SH_WORD_SPLIT
ls $args
If your target shells support arrays (ksh, bash, zsh), then you may be better off using an array:
args=(-a -l)
ls "${args[@]}"
From the zsh FAQ:
-
2.1: Differences from sh and ksh
The classic difference is word splitting, discussed in question 3.1; this catches out very many beginning zsh users.
3.1: Why does $var where var="foo bar" not do what I expect? is the FAQ that covers this question.
From the zsh Manual:
-
14.3 Parameter Expansion
Note in particular the fact that words of unquoted parameters are not automatically split on whitespace unless the option SH_WORD_SPLIT is set; see references to this option below for more details. This is an important difference from other shells.
-
SH_WORD_SPLIT
Causes field splitting to be performed on unquoted parameter expansions.