Zsh: glob case-insensitively with the (#i) glob flag and the no_case_glob option

By default, Zsh globs are case-sensitive, so *.jpg matches beach.jpg but not CAT.JPG or dog.Jpg:
$ ls photos/*.jpg
photos/beach.jpg
This is true even on macOS, where the filesystem is case-insensitive by default.
Zsh shares this behaviour with Bash, but provides per-glob and global controls to make your globs case-insensitive and match all the files you probably meant.
Per-glob with (#i)
To make a single glob case-insensitive, use the (#i) glob flag, which makes the rest of the pattern case-insensitive:
$ ls photos/*.(#i)jpg
photos/CAT.JPG photos/beach.jpg photos/dog.Jpg
Glob flags require the extended_glob option, which you can enable in your ~/.zshrc:
setopt extended_glob
Without it, Zsh treats (#i) as part of the pattern, leading to a confusing “no matches found” error.
Flag placement
(#i) applies from where it appears until the end of the pattern, including across directory separators. So you can put it at the start to make the whole pattern case-insensitive. For example, to find a README, however it’s capitalized:
$ ls (#i)readme*
README.md ReadMe.rst readme.txt
Or, to match a directory name of unknown case:
$ ls (#i)photos/*.jpg
Photos/CAT.JPG Photos/beach.jpg Photos/dog.Jpg
By default with no_case_glob
Case sensitivity is controlled by a few options, which you can check with set -o:
$ set -o | grep case
nocaseglob off
nocasematch off
casepaths off
set -o lists options that are on by default in their “no” form, so nocaseglob off means that the case_glob option is on, making globs case-sensitive. (case_match is the equivalent for regular expressions matched with =~.)
If you want all globs to be case-insensitive, you can turn on no_case_glob in your ~/.zshrc:
setopt no_case_glob
Then *.jpg matches CAT.JPG and friends, without any flag.
This applies to every directory in a path that contains a glob, so photos/*.jpg also matches files in Photos/. If you’d rather that literal directory names stay case-sensitive, also turn on the case_paths option:
setopt case_paths
Check out my new book Boost Your GitHub DX.
One summary email a week, no spam, I pinky promise.
Related posts:
- Zsh: uncover hidden files in globs with
(D) - Zsh: tab complete glob qualifiers
- Zsh: find the largest files with the
(OL)glob qualifier
Tags: zsh