I am looking for a ZSH equivalent to this BASH construct:

for file in *.{abc,def,ghi}; do #loop through all files with the extensions .abc, .def and .ghi

I cannot find a similar construct for ZSH. Or perhaps there is none?

  • 1
    The above works for me in zsh; what problem are you encountering? – Jeff Schaller Oct 7 '19 at 12:04

Suppose that you have the following files: foo.abc, bar.abc, qux.ghi. In bash, the loop body is executed four times: with foo.abc, bar.abc, *.def (with a literal *) and qux.ghi. In zsh, with default options, the loop is not executed at all, instead you get the error

zsh:1: no matches found: *.def

To both avoid running the loop on an unexpanded wildcard pattern and do run the loop on the existing files (if any), add the N glob qualifier.

for file in *.{abc,def,ghi}(N); do …

You can also use the | operator, so that you have a single pattern instead of multiple patterns. (Braces aren't a wildcard pattern, they're just a literal string expansion that happens before wildcards are parsed, i.e. *.{abc,def,ghi}(N) is just shorthand for *.abc(N) *.def(N) *.ghi(N))

for file in *.(abc|def|ghi)(N); do …

Note that you still need the N glob qualifier, otherwise you'll get an error if no file matches.

Instead of using the N glob qualifier, you can turn on the null_glob option (setopt null_glob). This often makes sense in scripts. Note that in bash, you would need to activate the similar option (shopt -s nullglob) to avoid running the loop body on unexpanded patterns.

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.