Especially for your case where the glob is $top/**/*.jpg
, I would not turn the caseglob
option off (same as turning nocaseglob
on¹) globally, as that affects all path components in glob patterns:
$ top=a zsh +o caseglob -c 'print -rC1 -- $top/*.jpg'
a/foo.jpg
a/foo.JPG
a/FOO.jpg
a/FOO.JPG
A/foo.jpg
A/foo.JPG
A/FOO.jpg
A/FOO.JPG
See how it did find all the jpg
and JPG
files in $top
(a
), but also the ones in an unrelated directory (A
) which just happened to have the same name but in upper case. Even if you don't have such directories, zsh will still look for them which means it needs to list the contents of every directory that makes up the components of $top
making that glob expansion more costly.
IMO, that nocaseglob
option is better left forgotten. It was only added to zsh for compatibility with bash
², and there most likely added to make the life of users of systems like Cygwin / macos that have case insensitive filesystem APIs easier.
Instead, I'd used the (#i)
glob operator (with extendedglob
) where you can specify which part of which glob should be case insensitive (similar to the ~(i)
of ksh93):
set -o extendedglob # needed for (#i)
for file in $top/**/*.(#i)jp(e|)g(NDn.); do
Or you can always do:
for file in $top/**/*.[jJ][pP]([eE]|)[gG](NDn.); do
as you would in sh
or any shell without case-insensitive glob operators.
Also note that *.jp(|e)g
instead of *.jp*g
which would match on filenames such as my.jpeg.import.log
for instance.
¹ or CASEGLOB
, CASE_GLOB
, C_A_se_G_lob
, case and underscores are ignored in option names, and the support of no
to turn an option off is to try and accommodate the mess with POSIX sh options (and other shells' including zsh itself) where some options are named with a no
prefix and some without for no immediately obvious reason.
² though the bash behaviour is different (and preferable IMO, at least on systems with case sensitive file names) in this instance in that a/*.jpg
would only find jpg
/JPG
files in a
, not A
as it only does case insensitive matching for path components that do have glob operators ([a]/*.jpg
would also find the jpg
/JPG
files in A
).
$top/**/*.(jpg|jpeg|JPG|JPEG)
if that is what you actually mean. If you usejp*g
and then make that case-insensitive, you'll match.jPEEg
, and.jp.rated-g
too. – Kusalananda Nov 21 '21 at 06:58