91

I would like to list all files matching a certain pattern while ignoring the case.

For example, I run the following commands:

ls *abc*

I want to see all the files that have "abc" as a part of the file name, ignoring the case, like

-rw-r--r-- 1 mtk mtk 0 Sep 21 08:12 file1abc.txt
-rw-r--r-- 1 mtk mtk 0 Sep 21 08:12 file2ABC.txt

Note

I have searched the man page for case, but couldn't find anything.

7 Answers 7

87

This is actually done by your shell, not by ls.

In bash, you'd use:

shopt -s nocaseglob

and then run your command.

Or in zsh:

unsetopt CASE_GLOB

Or in yash:

set +o case-glob

and then your command.

You might want to put that into .bashrc, .zshrc or .yashrc, respectively.

Alternatively, with zsh:

setopt extendedglob
ls -d -- (#i)*abc*

(that is turn case insensitive globbing on a per-wildcard basis)

With ksh93:

ls -d -- ~(i:*abc*)

You want globbing to work different, not ls, as those are all files passed to ls by the shell.

6
  • 1
    In bash, how to reset to original setting, If I use shport -s nocaseglob ?
    – mtk
    Commented Sep 21, 2012 at 17:11
  • 12
    @mtk: To set an option, you use shopt -s; to unset it, you use shopt -u. Alternatively, you can wrap everything in a subshell by using ( ) so that the setting doesn't affect the parent shell: (shopt -s nocaseglob ; ls *abc*).
    – ruakh
    Commented Sep 21, 2012 at 19:19
  • 1
    So there isn't any portable ways for this in POSIX or SUS or something like that (except for [aA][bB][cC])?
    – Timothy Gu
    Commented Nov 21, 2014 at 16:01
  • Excellent solution, I can't believe I hadn't come across shopt command in the last 15 yrs of using bash! Commented May 28, 2015 at 19:12
  • Jfg956's answer is the right one (next one). Why changing the shell behaviour when you have a regexp for that?
    – EnzoR
    Commented Nov 13, 2017 at 10:59
34

As explained by polemon, it is the shell (not ls) that extends *abc* to a list of files. This is called Pattern Matching.

Aside from changing the whole Pattern Matching behavior to ignore case, you could use another form of pattern matching than the *. The following would do what you want in bash:

ls *[aA][bB][cC]*

From bash man:

[...] Matches any one of the enclosed characters.

This allows more fine grain matching where you could use *[aA][bB]c* to match abc or ABc but not abC or ABC. Or an example in French, where I could want to match all instances of the e character:

ls *[eéèêëEÉÈÊË]*
4
  • 3
    Unfortunately, that approach quickly becomes unwieldy as the pattern gets longer. But for short things, it works.
    – derobert
    Commented Sep 21, 2012 at 18:37
  • @derobert: totally true, especially is (and it is probably the case) the shell has optimized the matching ignoring case by putting all the filenames and the match request in lower cases before comparing. However, the [...] can be useful in many cases, and I though it was worth mentioning.
    – jfg956
    Commented Sep 22, 2012 at 7:24
  • 2
    This is the right answer. Changing the shell behaviour is not.
    – EnzoR
    Commented Nov 13, 2017 at 11:00
  • If the locale is set properly, you should be able to use equivalence classes [[=e=][=E=]]. Commented Oct 3, 2018 at 17:35
21

You can also add -i (--ignore-case) option to grep to get and the below output.

[root@localhost ~]# ls -l | grep -i abc
-rw-r--r--  1 root root    0 Feb 25 20:41 fileabc.txt
-rw-r--r--  1 root root    0 Feb 25 20:41 fileABC.txt
2
  • 1
    Pattern matching has a better performance compared to grep because grep needs to gather everything and then filter. Has a noticeable difference when working with larger folder.
    – Omi
    Commented Aug 9, 2018 at 16:50
  • @Omi Additionally, regular expressions are for text, specifically lines of text. Filenames may contain newlines.
    – Kusalananda
    Commented Aug 9, 2018 at 17:08
6

I don't think this is possible with ls, but you could use find instead:

find . -maxdepth 1 -iname '*abc*'
1
  • .....Except that you have to remember that if you specify something that matches a directory, you're going to get the name of the directory, not the contents of it. So it's not a 1:1 replacement for ls. I believe that not allowing an ls --ignore-case is an oversight. Commented Feb 21, 2021 at 18:41
0

use the following code:

LC_COLLATE=en_US ; export LC_COLLATE
ls *abc*
LC_COLLATE=C ; export LC_COLLATE
2
  • What is the LC_COLLATE variable for ? can you explain further.
    – mtk
    Commented Oct 21, 2012 at 10:26
  • click on the link to know about this @mtk Commented Nov 4, 2012 at 19:08
0

You can GREP the file using -i which adds the insensitive option.

For example to find both abc and ABC you can run this command

    [root@mtk bin]# ls -l | grep -i abc
    640K -rw-r--r-- 1 mtk mtk 639K Sep 21 08:12 file1abc.txt
    676K -rw-r--r-- 1 mtk mtk 674K Sep 21 08:12 file2ABC.txt
2
  • 5
    Luis Perez I think you haven't used -i option anywhere in you command.
    – AReddy
    Commented Feb 25, 2016 at 15:29
  • also Why not parse ls?
    – phuclv
    Commented Mar 9, 2017 at 11:19
-3

In tcsh, set an alias in .aliases

alias lsnc "ls BS!* | sort -f "

("BS" = one "backslash"; I had to use this to get it to show up in my browser.)

and use lsnc instead of ls

In bash, try an alias in .bash_aliases like

lsnc() { ls $1 | sort -f ; }

With options to ls, e.g., ls -l, here is a simple fix:

tcsh:

alias lsncl "ls -l BS!* | sort -f -k 9"

bash:

lsncl() { ls -l $1 | sort -f -k 9 ; }
4
  • Are you sure you are not missing a '=' after lsnocase?
    – Anthon
    Commented Aug 29, 2013 at 21:09
  • Anthon: The (revised) lsnc and lsncl work for me under tcsh and bash on both Cygwin and Ubuntu. Note that for bash, I'm using a function, not an "alias" per se. Lester Commented Aug 31, 2013 at 0:07
  • Anthon: Yes, you likely can use alias in bash, like alias lsncl='ls -l $1 | sort -f -k 9' Commented Aug 31, 2013 at 0:13
  • This answer does not address the specific question which wants to pass the files passed to ls to be treated as a case-insensitive. If the shell passes passes too few files to ls, there's nothing ls and sort can can to fix the situation. As noted in other answers, the problem needs to solved in the shell, not with an ls syntax. Commented Sep 14, 2015 at 18:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .