Handling Multidigit Ranges of Files in Lexicographical Order in Zsh

wildcardszsh

I would like to specify a range of files (in lexicographical order) with two integers (e.g. 2 to 57) in zsh by globbing.

For example: "pick the files 2 to 57 in lexicographical order under the path that matches some globbing pattern".

I thought using square brackets would do it

 for x in /foo/bar/*[2-57]; do print $x; done

but zsh apparently thinks I am asking for the files 2 to 5 (or something like that) instead of files 2 to 57. Any thoughts why? How can I accomplish this?

Best Answer

[2-57] is a character set consisting of 2, 3, 4, 5 and 7, in zsh and every other wildcard and regexp syntax out there. Your glob pattern *[2-57] matches every filename whose last character is one of those five digits.

I think you are misremembering the syntax of the [m,n] glob qualifier. Glob qualifiers always go in parentheses at the end of the pattern, and the range separator is a comma. The pattern *([2,57]) expands to the 2nd, 3rd, …, 57th matches. The default expansion order is lexicographic (with some special magic to sort numbers in numeric order if the numeric_glob_sort option is set); you can control it with the o or O glob qualifier (e.g. *(om[2,57]) to match the 57 most recent file except the one most recent file).

for x in /foo/bar/*([2,57]); do print $x; done

Not what you asked for, but related and possibly useful to future readers: if you want to enumerate files 2 to 57 whether they exist or not, you can use a range brace expression. This feature also exists in bash and ksh.

echo hello{2..57}

And if you want to match files whose name contains a number between 2 and 57, you can use the pattern <2-57>. This is specific to zsh.

$ ls
file1 file2 file3 file57 file58
$ echo file<2-57>
file2 file3 file57

Note that a pattern like *<2-57> is likely not to do what you expect, because the * could match digits too. For example, file58 matches *<2-57>, with file5 matching the * part and 8 matching the <2-57> part. The pattern *[^0-9]<2-57> avoids this issue.

Related Question