How to do case-sensitive globbing for wildcards in bash

How can I search a folder for files ending in “.JPG”? Typing in “ls *.JPG” and “ls *.jpg” both generate the same result – a list of files including those ending in both .JPG and .jpg, regardless of case.

In the old days (korn shell and c-shell) this used to work as expected. But with bash globbing, the use of wildcards no longer works intuitively. I’ve done a lot of searching on “ls”, “bash”, and “globbing”, but what I found suggests that case-sensitive expansion is the default and “nocasematch” needs to be set to change it.

My .bashrc file is currently unchanged from the install - there are only three shopt commands and none of those should impact wildcard expansion or globbing. I am using the Konsole command-line tool from withing KDE Plasma, both unchanged from the original install.

Is there possibly a global .bashrc file that is setting “nocasematch” for bash?

Correct, except it’s nocaseglob. You can turn it off with shopt -u nocaseglob, but you probably already know that.

Descriptions of the two options

nocaseglob

If set, Bash matches filenames in a case-insensitive fashion when performing filename expansion.

nocasematch

If set, Bash matches patterns in a case-insensitive fashion when performing matching while executing case or [[ conditional commands (see Conditional Constructs, when performing pattern substitution word expansions, or when filtering possible completions as part of programmable completion.

The Shopt Builtin (Bash Reference Manual)

It’s not enabled by default, and for me globbing works as expected in both yakuake and konsole.

shopt -s globstar

grep "nocaseglob" ~/**/.*  2> /dev/null
grep "nocaseglob" /etc/**/.*  2> /dev/null
grep "nocaseglob" /usr/**/.*  2> /dev/null

shopt -u globstar

May be it’s a good time to start using fd instead of ls… :wink:

Arguments in lowercase are case insensitive, in uppercase or with -s are case sensitive.

Having test.jpg and test.JPG

fd jpg$ → shows both
fd JPG$ → shows only uppercase
fd -s jpg$ → shows only lowercase

1 Like

I added the following line at the end of my .bashrc…

shopt -u nocaseglob

But after opening a new window in Konsole “ls .JPG” still displays .jpg files.

The other odd thing is that, when entering command “shopt -q nocaseglob”, the system responds with message “zsh: command not found: shopt”. Are shopt commands only allowed in .bashrc files?

Oh, and why does bash think I’m running zsh instead of bash? My SHELL variable is set as follows…

SHELL=/bin/bash

Not sure what you expect that to do. Use -s to enable and -u to disable.

No, but it’s a bash buit-in so you can only use it in bash.

Presumably because you are running zsh.

This is more accurate:

echo $0

Add this to the end of your .zshrc

setopt CASE_GLOB

then source it

source ~/.zshrc

If you prefer to use bash then create a profile (or edit an existing one) in Konsole and set it to use /usr/bin/bash for the “Command”

Konsole → Burger Menu → Settings → Configure Konsole → Profiles

Then add shopt -u nocaseglob to the end of your ~/.bashrc and source ~/.bashrc

1 Like

You’re right – echo $0 returns “/bin/zsh”. So much for global environment variables.

I added the following line to ~/.zshrc…

unsetopt CASE_GLOB

I then ran the following command…

source ~/.zshrc

But after opening a new shell, ls *.JPG still shows both .JPG and .jpg files.

1 Like

That’s KDE for you, always trying to break things do things differently.

Sorry that was a typo, it should be setopt CASE_GLOB

If you’ve invoked bash from a zsh shell, $SHELL will still show zsh:

``
$ echo $SHELL
/usr/bin/zsh
$ bash
$ echo $SHELL
/usr/bin/zsh
``

1 Like

That worked. Thanks for the help!

My first exposure to zsh. I guess I need to figure out why KDE thinks I should be using zsh instead of bash. I’m guessing bash was OK after all, because I had a simple bash script that seemed to be working “correctly”.

2 Likes

Great. :smiley:

KDE like to do things differently and as such they’ve made Konsole profiles take precedence (so chsh doesn’t have quite the desired effect in Plasma). You have to change it in the Konsole profile like I explained a couple of posts back.

Scripts should have a shebang on the first line, that tells the shell which interpreter to use. Actually it’s the command to run the script with.

If you don’t have a shebang then it’s run with sh, which nowadays is actually a symlink to bash.

Shebang basics

If you have a script with this shebang line

#!/usr/bin/bash

and run it like so

$ path/to/script

# we get the command from the shebang
# and the path to the script is passed in
/usr/bin/bash /path/to/script

So you’re starting a new shell for the script to run in.

You can use a single option too (or multiple short options together), and do weird things like use echo or ls

$ echo "#\!/usr/bin/echo" > /tmp/test
$ chmod +x /tmp/test
$ /tmp/test
/tmp/test

$ echo "#\!/usr/bin/ls -l" > /tmp/test
$ /tmp/test
-rwxr-xr-x 1 dm dm 17 Oct 15 21:51 /tmp/test

# ls -li would work 
# ls -l -i won't work

Edit:

I’ll take the liberty of marking the solution this time, in future you can click the below a post to mark that as the solution, if you can’t see it then click the button with 3 dots …

Edit 2:

Removed bit about $0 as I was remembering incorrectly.

1 Like

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.