9

I run the following code

zgrep -c compinit /usr/share/man/man{1..9}/zsh*

I get

zsh: no matches found: /usr/share/man/man2/zsh*

This is strange, since the following works

echo Masi{1..9}/masi

This suggests me that the problem may be a bug in Zsh.

Is the above a bug in Zsh for {1..9}?

chaos
  • 122,029
  • 33
  • 303
  • 309
Léo Léopold Hertz 준영
  • 134,464
  • 179
  • 445
  • 697

2 Answers2

11

In zsh, if you want to use ranges in filenames, zle offers <1-n> on any real names it can expand on. That is to say:

$ touch a0b a1b a5b a7b
$ print a<0-100>b

And then hit <Tab> right after the final b would leave you with print a0b a1b a5b a7b expanded on the line.

For all other intents and purposes - perhaps full range requirements, non-file and scripting use - I'd express this using the rather succinct idiomatic zsh loop as:

for n ({1..50}); do print $n; done

Will allow you process the whole sequence range of numbers 1 to 50 :) after which you can do all sorts of useful things with, such as a file collection that doesn't exist yet:

arr=($(for n ({1..50}); do print /my/path/file$n.txt; done)) && print $arr[33]
Rob Jens
  • 584
  • 6
  • 8
11

It's not a bug, and it is working inside words fine. The trouble you're having here is that {1..9} is not a wildcard expression like * is; as your echo example shows, it's an iterative expansion. So your zgrep example is exactly the same as if you had typed each alternate version into the command line, and then since there are no man pages starting with zsh in man2, it errors out. (It's erroring out on a failure to find a match, not anything intrinsically related to your brace sequence expansion.)

If you did this, on the other hand:

zgrep -c compinit /usr/share/man/man[1-9]/zsh*

you'd get the results you expect, because [1-9] is a normal wildcard expression.

chaos
  • 122,029
  • 33
  • 303
  • 309
  • So we have two spaces: one is non-wildcard and the other is wildcard space. If there exists one wildcard, it forces me to use only wildcard characters. In the same way, you can only use non-wildcard characters alone. - - Thank you for your answer! – Léo Léopold Hertz 준영 Apr 30 '09 at 05:03
  • 2
    @Masi: Not quite. If I had a directory with 1-hello.gif, 2-world.gif, ..., 20-foobar.gif, `{1..20}-*.gif` would work perfectly fine to match them, while `[1-20]-*.gif` would only match the first two. This will cause the same error as in your question if any of the sequentially-numbered files are missing, though. – ephemient Apr 30 '09 at 15:38
  • @ephemient: Do you mean that [1-20]File does not work if you do not have, for instance, 7File? -- If so, what is the benefit of using [1-20] instead of {1..20} which does not cause you the problem? – Léo Léopold Hertz 준영 May 24 '09 at 18:48
  • @Masi: He means that [1-20] does not mean one through twenty; it means the same thing as [120], i.e. any of 1, 2, or 0. The range functionality in [] is only good for the range from one character to another character, like A-Z, a-z, 0-9. It doesn't do ranges like 1-20; for those you have to do other maneuvers. – chaos May 24 '09 at 20:16
  • The [] (group) notation is basically the same as commonly found in regular expressions; the same restrictions apply. – dom0 Mar 07 '13 at 16:37