I am using zsh 5.4.2. The function that is causing issue is:

function zp () {
    zparseopts -E -watch:=o_watch -show=o_show
    echo "show            : $o_show"
    echo "watch           : $o_watch"


$ zp  --show --watch "Watching"
show            : --show
watch           : --watch Watching
$ zp  --watch --show 
show            : 
watch           : --watch --show

You can see that, If I do not pass a value to --watch (which's argument is mandatory) then it takes the next option in this case --show as the argument. It should actually show an error like zp:zparseopts:1: missing argument for option: -watch

Why is --watch taking --show as an argument instead of throwing an error?

  • 1
    That's not specific to zsh. Most tools I know do the same thing (e.g., grep -f -e ... will look for a file named -e).
    – muru
    Jun 16 '20 at 10:45
  • I did not know that, I thought it was a bug.
    – blueray
    Jun 16 '20 at 11:05
  • So, how to throw an error if someone mistakenly do not give argument to a mandatory option (using zparseopts).
    – blueray
    Jun 16 '20 at 11:11
  • 1
    If you are absolutely certain that the argument cannot begin with a -, then you can check for that. But in general, that's not always true. (For example, that's one of the main uses of -e with grep: If you want to look for the pattern -v in a file, you would need grep -e -v .... That -v is a valid option should not block the use of -v as an argument to -e.)
    – muru
    Jun 16 '20 at 11:28

For comparison, I'm pretty sure that's how the GNU C function getopt_long also works, e.g. with GNU ls:

$ ls --sort --foo
ls: invalid argument ‘--foo’ for ‘--sort’
Valid arguments are:

If you made the argument to --walk optional, zparseopts would take --watch --show as two arguments:

In all cases, option-arguments must appear either immediately following the option in the same positional parameter or in the next one. Even an optional argument may appear in the next parameter, unless it begins with a ‘-’.

But it seems that the user just needs to know which options take arguments, which also happens with short options, e.g. tar -tzf is quite different from tar -tfz.

Using (only) --sort=whatever would, in my opinion, make it clearer, but zparseopts doesn't even really support = directly. (--sort=whatever would give =whatever as the argument value). And that doesn't really work for short options.

  • this is how I handle the = when parsing opts sort=${${sort:+"${sort[2]/#=/}"}:-default}
    – NorthIsUp
    Oct 5 '20 at 23:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.