Case-insensitive Glob on zsh/bash
Asked Answered
E

6

49

I need to list all files whose names start with 'SomeLongString'. But the case of 'SomeLongString' can vary. How?

I am using zsh, but a bash solution is also welcome.

Ersatz answered 1/10, 2008 at 9:56 Comment(0)
O
41

ZSH:

$ unsetopt CASE_GLOB

Or, if you don't want to enable case-insensitive globbing in general, you can activate it for only the varying part:

$ print -l (#i)(somelongstring)*

This will match any file that starts with "somelongstring" (in any combination of lower/upper case). The case-insensitive flag applies for everything between the parentheses and can be used multiple times. Read the manual zshexpn(1) for more information.

UPDATE Almost forgot, you have to enable extendend globbing for this to work:

setopt extendedglob
Optimistic answered 1/10, 2008 at 12:50 Comment(2)
What about setopt no_CASE_GLOB?Stob
For what it's worth, if you have nocaseglob set, then you can use (#I) to temporarily undo it, for a case-sensitive glob.Flacon
Q
41

bash:

shopt -s nocaseglob
Quipster answered 1/10, 2008 at 10:11 Comment(1)
Thanks. I was hoping there was a way to specify it as part of the glob itself. The zsh manual mentions something like it but I was not able to figure it out.Ersatz
O
41

ZSH:

$ unsetopt CASE_GLOB

Or, if you don't want to enable case-insensitive globbing in general, you can activate it for only the varying part:

$ print -l (#i)(somelongstring)*

This will match any file that starts with "somelongstring" (in any combination of lower/upper case). The case-insensitive flag applies for everything between the parentheses and can be used multiple times. Read the manual zshexpn(1) for more information.

UPDATE Almost forgot, you have to enable extendend globbing for this to work:

setopt extendedglob
Optimistic answered 1/10, 2008 at 12:50 Comment(2)
What about setopt no_CASE_GLOB?Stob
For what it's worth, if you have nocaseglob set, then you can use (#I) to temporarily undo it, for a case-sensitive glob.Flacon
B
17

Depending on how deep you want to have this listing, find offers quite a lot in this regard:

find . -iname 'SomeLongString*' -maxdepth 1

This will only give you the files in the current directory. Important here is the -iname parameter instead of -name.

Bunk answered 1/10, 2008 at 10:10 Comment(0)
H
3

$ function i () {
> shopt -s nocaseglob; $*; shopt -u nocaseglob
> }
$ ls *jtweet*
ls: cannot access *jtweet*: No such file or directory
$ i ls *jtweet*
JTweet.pm  JTweet.pm~  JTweet2.pm  JTweet2.pm~
Horbal answered 1/10, 2011 at 4:11 Comment(1)
You need to quote the glob to pass it to the function safely. If *jtweet* matches anything, it will be expanded before the function sees it. (Or error or empty string depending on other shopt settings). Interesting idea, though. I think it will mostly work if you run i ls '*jtweet*', even if there's also a `jtweet.pm in the directory. There are lots of potential problems with spaces or other special characters in non-glob args, or in the glob, though.Creation
C
1

For completeness (and frankly surprised it's not mentioned yet, even though all the other answers are better and/or "more correct"), obviously one can also use (especially for grep aficionados):

$ ls | egrep -i '^SomeLongString'

One might also stick in a redundant ls -1 (that's option "one", not "ell"), but when passed to a pipe, each entry is already going to be one per line, anyway. I'd typically use something like this (vs set) in shell scripts, eg in a for/while loop: for i in $(ls | grep -i ...) . However, the other answer using find would be preferable & more flexible in that circumstance, because you can, for example, omit directories (or set other restrictions): for i in $(find . -type f -iname 'SomeString*' -print -maxdepth 1)... or even forgo the loop altogether and just use the power of find all by itself, eg: find ... -exec do_stuff {} \; ... , but I do digress (again, for completeness.)

Corie answered 5/11, 2019 at 4:38 Comment(0)
B
1

For completeness, a long, full solution (creating thumbnails from a list of camera images):

_shopt="$( shopt -p )"
shopt -s nocaseglob
for f in *.jpg; do
    convert "$f" -auto-orient -resize "1280x1280>" -sharpen 8 jpeg:"$( basename "$f" ".${f##*.}" ).shelf.jpg"
done
eval "$_shopt"

Since we don't know exact extension case (.jpg or .JPG), we create it from the name itself by stripping the prefix up to (and including) the last dot. The -auto-orient option will take care of image orientation so that thumbnails would be viewed correctly on any device.

Butlery answered 2/7, 2022 at 12:18 Comment(1)
For zsh change shopt to setopt.Selden

© 2022 - 2024 — McMap. All rights reserved.