How to filter a glob in zsh

wildcardszsh

Basically I can use a glob in zsh to a list. Often, it turns out, I would like to filter that list, grep'ishly I'm wondering though, if I need to do that.

Does zsh have a method to filter a list? I fear this is an obvious question, but it's a low yield day today, mentally.

Best Answer

This is kind of a weird question, seeing as zsh is the only shell with this feature. It's called glob qualifiers. The manual is, as usual, rather terse and devoid of examples. The Zsh-lovers page has a few examples. Googling zsh "glob qualifiers" turns up a few blog posts and tutorials. You can also search for "glob qualifier" on this site.

The basics: glob qualifiers are in parentheses at the end of the glob. The most useful ones are the punctuation signs to select only certain file types.

echo *(/)      # directories
echo *(.)      # regular files
echo *(@)      # symbolic links
echo *(-/)     # directories and symbolic links to directories

There are other qualifiers to filter on metadata such as size, date and ownership.

# files owned by the user running zsh, over 1MB, last modified more than 7 days ago
echo *(ULm+1m+7)

Glob qualifiers can also control the order of matches, and restrict the number of matches.

echo *(Om[1,10])     # The 10 oldest files

You can set up arbitrary filters by calling a function, with the + qualifier (you can even put the code inline with the e qualifier, if you don't mind the tricky quoting).

Note that unfortunately all of this only works on globs. If you want to build a list of file names this way, you need to filter when you're globbing. If you want to filter a list that you've already built, there's a completely different syntax, parameter expansion flags, which can only perform simple text filtering ("${(@)ARRAY:#PATTERN}").