267

I am looking for file "WSFY321.c" in a huge directory hierarchy.
Usually I would use GNU find: find . -name "WSFY321.c"
But I do not know the case, it could be uppercase, lowercase, or a mix of both.

What is the easiest way to find this file?
Is there something better than find . | grep -i "WSFY321.c" ?

Nicolas Raoul
  • 7,945
  • 14
  • 43
  • 55

3 Answers3

353

Recent versions of GNU find have an -iname flag, for case-insensitive name searches.

find . -iname "WSFY321.c"
d-cubed
  • 204
  • 3
  • 21
Lars Rohrbach
  • 5,143
  • 2
  • 20
  • 24
  • 7
    Also, since you're specifically looking for a file you can *probably* shave another couple of ticks off that with the `-type f` flag so it won't bother looking at the name if the inode is a directory. But that's pedantic levels of optimization... – Shadur Feb 20 '12 at 09:47
  • For working with some regex you can do `find . -iname \*WSFY321.c\* -type f` – Benj Jun 11 '16 at 22:01
  • 1
    This pattern of adding `-i` before an option follows for other `find` options too. Ex: `-name` to search for a name, and `-iname` to make it case-insensitive. `-path` to search for a path, and `-ipath` to make it case-insensitive. I mention using `-ipath` in my answer here: [Stack Overflow: How to exclude a directory in find . command](https://stackoverflow.com/a/69830768/4561887). – Gabriel Staples Nov 03 '21 at 19:40
54

With GNU find, or other versions of find that have it:

find . -iname 'WSFY321.c'

With other versions:

find . -name '[Ww][Ss][Ff][Yy]321.[Cc]'

Or a compromise that's slower but easier to type:

find . -name '????321.c' | grep -i '/WSFY[^/]*$'

Or in zsh:

print -rl -- **/(#i)WSFY321.c
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
  • *@Gilles* The `grep` version is filtering only upper case, and I don't understand the '[^/]' ..(not /) – Peter.O Feb 20 '12 at 06:22
  • @Gilles What is the argument to use the single quotes in the first case (exact filename) over no quotes at all? – Bernhard Feb 20 '12 at 07:14
  • @Peter.O No `*` after the `/` in the bash version. I meant `grep -i`. I use `[^/]*` rather than `.*` so as not to catch files in directories whose name begins with `WSFY`. – Gilles 'SO- stop being evil' Feb 20 '12 at 10:08
  • 6
  • Thanks Gilles: I deleted the previous comment with incorrect syntax, and tested the ammended version, but it doesn't work without the \* (for an unexpected reason; to me at least).  The case-insensitive option no longer works: `shopt -s extglob nocaseglob globstar; printf '%s\n' **/WSFY321.c` ... I suppose that's why it is called a *nocase‍​* ***glob***: it only works in the context of a glob (or so it seems). – Peter.O Feb 20 '12 at 11:34
  • PS: Here is a way to use bash's *nocaseglob* without using the asterisk **\*** wildcard: `shopt -s extglob nocaseglob globstar; printf '%s\n' **/[W]SFY321.c` ... The `[]` is *globby* enough... – Peter.O Feb 20 '12 at 11:45
  • @Peter.O Oh, I didn't expect this either. Bash is being weird. `**/WSFY321.[c]` does work. Zsh behaves in the same way if you use `setopt no_case_glob`, but using the case insensitive glob flag tells the shell that this is a glob anyway (and it's the same in ksh93 with `**/~(i:WSFY321.c)`). – Gilles 'SO- stop being evil' Feb 20 '12 at 11:54
  • PPS: The newer extended globing syntax in bash works without any quirky juggling involved: `shopt -s extglob nocaseglob globstar; printf '%s\n' **/@(WSFY321.c)` – Peter.O Feb 20 '12 at 12:10
3

Two solutions for macOS:

Using GNU find:

brew install findutils --with-default-names
# restart Terminal
find . -iname 'WSFY321.c'

Using GNU sed:

brew install gnu-sed --default-names
# restart Terminal
find -name "$(sed 's|\([[:alpha:]]\)|[\U\1\L\1]|g' <<<'WSFY321.c')"
srage
  • 131
  • 4