4

The man page for grep reads

-i, --ignore-case

      Ignore case distinctions in both the PATTERN and the input files.  (-i is specified by POSIX.)

However, if I change case on a filename, it won't work.

$ touch WHATEVER
$ grep -i pattern whatever
grep: whatever: No such file or directory

Am I missing something?

  • Comments are not for extended discussion; this conversation has been moved to chat. – terdon Apr 18 at 10:29
  • 8
    That switch is talking about the content of the file, not its name. The accepted answer does not at all address the problem shown here. – Monty Harder Apr 18 at 14:54
  • @MontyHarder The accepted answer implicitly confirms that the wording is confusing and supports that this is a non-issue in the new version. – grep Apr 18 at 15:11
  • 4
    @grep The problem you present is the non-existence of whatever, which the accepted answer does not in any way address. I am not aware of any version of grep that will look in WHATEVER when you ask it to look in whatever, under any circumstances. The accepted answer addresses grep -i PATTERN whatever, which is not grep -i pattern WHATEVER. Case-sensitivity of filenames is a *nix thing, not a grep thing. – Monty Harder Apr 18 at 17:39
  • 3
    I would never have considered the -i parameter to apply to the filename, based on reading either man page line. – Criggie Apr 18 at 21:24
15

That confusing snippet was changed in newer versions of GNU grep to:

-i, -ignore-case Ignore case distinctions, so that characters that differ only in case match each other.

See this commit: http://git.savannah.gnu.org/cgit/grep.git/commit/?id=e1ca01be48cb64e5eaa6b5b29910e7eea1719f91

 .BR \-i ", " \-\^\-ignore\-case
-Ignore case distinctions in both the
-.I PATTERN
-and the input files.
+Ignore case distinctions, so that characters that differ only in case
+match each other.

As to where the old formulation may originate, some programs like less(1) have a (mis)feature[1] where using an uppercase letter in a pattern will turn off case insensitivity for a particular search (override the -i flag). The author of that doc snippet probably assumed that many people expected that behavior, and instead of some direct caveat, preferred that non-committal sentence. FWIW, such a feature was never a part of ed(1), grep(1), vi(1), perl(1) etc. or of the regex(3) or pcre(3) APIs.

[1] that seems to have its origins in emacs, where it's the default; there you can turn it off by setting the (customizable) search-upper-case variable to nil.

  • Do you mind opening that link in private mode finding that part of the doc? I just went through all ten occurrences of "ignore" and couldn't find that bit. – grep Apr 17 at 23:57
  • 1
    I find the less behaviour very useful. I would never use uppercase characters in my search query if I intended the search to be case sensitive. It's a sensible default IMO – Stéphane Chazelas Apr 18 at 11:16
  • 1
    @StéphaneChazelas Having to edit a mixed-case word that was copy-pasted is not nice, and that feature is non-symmetric -- what is the syntax to search in less -i for "hello" but not "Hello"? As to the interaction between case insensitive search, compatibility chars like and locales, there are many nasty problems (while there, don't forget the titlecasing (eg Lj, lj , LJ = U+01C7-U+01C9), another horrible contraption for a non-existing problem). – mosvy Apr 18 at 12:39
  • 1
    You can get all those behaviours in less by entering -i and -I within less. The default is case-sensitive, -i is the default chosen by mandb, git, and IMO is useful. For a complete case insensitive (like for your copy-paste case), there's -I. vim has the smartcase option as an equivalent of less -i behaviour. GNU info and GNU emacs behave like less -i in this instance. – Stéphane Chazelas Apr 18 at 15:12
  • 1
    What does any of this have to do with mis-cased filenames? – Monty Harder Apr 18 at 17:47
6

Apparently I have a different manpage.

   -i, --ignore-case
          Ignore case distinctions, so that characters that differ only in
          case match each other.

In any case, it's not about the filenames.

It ignores case in the file (contents) but also in the pattern.

Test file:

___________
Hello World
^^^^^^^^^^^

Grep results (ignore case of file contents):

$ grep hello test.txt 

$ grep Hello test.txt 
Hello World
$ grep -i HELLO test.txt 
Hello World
$ grep -i hello test.txt 
Hello World

Grep results (ignore case of pattern):

$ grep [a-Z] test.txt 
grep: Invalid range end
$ grep -i [a-Z] test.txt
Hello World
$ grep -i [A-z] test.txt
Hello World
$ grep [A-z] test.txt
___________
Hello World
^^^^^^^^^^^

As you can see the results can sometimes be a little unexpected.

Not sure if there is an example where this actually matters more.

  • 1
    "It ignores case in the file (contents) but also in the pattern", this suggests (although it doesn't necessarily say it), that it is possible to ignore case in the pattern, but not in the contents. I'd like to understand how this would work (ignoring pattern, but not contents -- or the other way around). – grep Apr 17 at 23:41
  • 2
    In less, for example, there's a -i mode in which matching is case-insensitive if you only use lowercase letters in the pattern, but if there are any uppercase letters in the pattern, the whole thing is case-sensitive. That's like (sometimes) ignoring case in the contents but not the pattern. – user41515 Apr 17 at 23:48
  • less is an interactive program quite unlike grep, not sure how it relates at all. interactive programs make usability choices, like nano where you can change case-sensitivity by hotkey. As for the manpage I think the old text actually explained it better, the new one does not make clear the pattern meaning itself changes too (even if [A-z] example is a bit constructed, the match result is completely different, so it should be in the manpage, but isn't anymore). – frostschutz Apr 18 at 10:01
6

"It ignores case in the file (contents) but also in the pattern", this suggests (although it doesn't necessarily say it), that it is possible to ignore case in the pattern, but not in the contents.  I'd like to understand how this would work (ignoring pattern, but not contents -- or the other way around).

Well, for example, it could be written so that a pattern of “hello” would match “Hello” in the file, but not vice versa.  While this sounds hypothetical, it is the way spell-check works.  If your dictionary contains “stack” and “exchange”, and your document contains “Stack Exchange”, spell-check will succeed without error.  But if your dictionary contains “Unix” and your document contains “unix”, that will be flagged as an error.

6

Using the -i flag ignores the case of the matches, not the case of the filenames. You created a file whose name is all uppercase, but you told grep to open a file whose name is lowercase, leading to the "file not found" error message. Linux filenames are case-sensitive.

0

"in both the PATTERN and the input files" = "in the pattern and in the input files". The preposition "in" applies to both clauses joined by "both".

If the authors had intended to ignore case distinctions in both the PATTERN and the input filenames, they would have said so.


In comments, OP explains that the Question is incorrectly framed. In response to OP's actual difficulty: The first line of the description on the man page you cite is "grep searches the named input FILEs (...) for lines containing a match to the given PATTERN." That is, grep searches for matches to the contents of files not for matches to their names.

Of course, OP's clarification makes the accepted answer nonresponsive to the hidden question.

  • That doesn't address my problem at all. I interpreted it as you suggest. I take issue with the meaning of "files". Why should it mean "file's contents"? I interpreted it as it being their names. Ultimately a file is neither its contents, nor their names. – grep Apr 19 at 9:30
  • Another thing that led to my confusion and led to the above-mentioned point, is that "ignoring case in the pattern, but not in the contents" is a concept that is extremely alien to me. In my mind if case is ignored in the pattern, then it is also ignored in the contents. Why then, reference contents if it is not possible to ignore case in the pattern, but not in the contents? I thought "OK, if this is being referenced, then surely it doesn't mean the file's contents, but the filenames". – grep Apr 19 at 9:31
  • @grep : You did not interpret it as I suggest. "in files" is not their filenames. Filenames are on the outside of files. For example, where in the file whatever is the string "whatever"? – Eric Towers Apr 19 at 9:32
  • I interpreted it as "in the pattern and in the input files". The thing is, you look at the word files here and think of its contents. I do not. What I meant with "I interpreted as you suggest" is that your rewording doesn't address my issue at all. It could have be worded as you suggest, and it would have led to my confusion anyway. – grep Apr 19 at 9:34
  • 1
    @grep : Either you read the first line of the description that directly informs you that grep searches the lines in files for matches or you didn't. Since apparently you did not read that line, you have no basis to complain that the documentation is incorrect. – Eric Towers Apr 19 at 9:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.