tags:

views:

491

answers:

5

This question is based on this answer.

Why do you get the same output from the both commands?

Command A

$sudo grep muel *                                                             /tmp
masi:muel

Command B

$sudo grep -H muel *                                                          /tmp
masi:muel

Rob's comment suggests me that Command A should not give me masi:, but only muel.

In short, what is the practical purpose of -H?

+5  A: 

Grep will list the filenames by default if more than one filename is given. The -H option makes it do that even if only one filename is given. In both your examples, more than one filename is given.

Here's a better example:

$ grep Richie notes.txt
Richie wears glasses.

$ grep -H Richie notes.txt
notes.txt:Richie wears glasses.

It's more useful when you're giving it a wildcard for an unknown number of files, and you always want the filenames printed even if the wildcard only matches one file.

RichieHindle
Happy to help. (But why did you accept my answer and then remove the accept?)
RichieHindle
@Richie: Bobby's answer is excellent. I did not know before about the practical implications of the option.
Masi
@Masi: Just curious - don't feel pressured into re-accepting my answer if Bobby's is better.
RichieHindle
+4  A: 

If you grep a single file, -H makes a difference:

$ grep muel mesi
muel

$ grep -H muel mesi
masi:muel

This could be significant in various scripting contexts. For example, a script (or a non-trivial piped series of commands) might not be aware of how many files it's actually dealing with: one, or many.

Bobby Jack
Could you give an example where it is useful to use the option `-H`, please. I have never needed it before.
Masi
If you pipe, grep will read from standard input. That means no file names.
Zr40
Hmm.. tricky off the top of my head. I can imagine a script that 'walks' through a bunch of directories, collecting file names from each that a given term appears in, passing the results of 'grep' to cut. -H would guarantee filenames, even if only a single file was searched in the first place. That's not a GREAT example, but it's a specific as I can be at short notice! :)
Bobby Jack
@Zr40: good point, although I guess I was thinking more of the output FROM grep being piped elsewhere (see other comment)
Bobby Jack
Working with `xargs` is one place; if there's just one file sent to it, then the `grep` will not print the file name unless you either tell it to (GNU `grep -H`, but not POSIX `grep`) or unless you use '`xargs grep whatever /dev/null`' so that `grep` always sees at least two file names (actually, if it is given no names, `xargs` still runs `grep something /dev/null`, but that produces no output - probably what was wanted anyway). You can also get this effect if `xargs` processes files in batches of 20, and you have 41 files in total. It is exasperating not to see the last file name!
Jonathan Leffler
@Jonathan: How can you show that it is exasperating to see the last filename? --- I would like to feel that.
Masi
@Masi: suppose you've just run a 'find' operation over a 200 GB disk drive, and it took an hour and a half to do the grepping. You got one file with results - but 'grep' didn't show you the file name because it was the very last file looked at, and it was the only file in the command list produced by 'xargs'. You now know that the data exists in a file - but you don't now which one; you've got to redo that entire 'find' command again (maybe not the 'xargs' and 'grep', so it will be quicker, but ...). That would be frustrating to me.
Jonathan Leffler
@Jonathan: Great example! Thank you!
Masi
+1  A: 

When you grep from multiple files, by default it shows the name of the file where the match was found. If you specify -H, the file name will always be shown, even if you grep from a single file. You can specify -h to never show the file name.

Zr40
A: 

These examples are based on Bobby's answer.

#1

I run

cat COPYING | grep -H is

I get

...
(standard input): of liability, arising in any way out of the use of
(standard input): this information, even if advised of the possibility
...

#2

I run

cat COPYING | grep -H is *

I get

...
COPYING:library.  If this is what you want to do, use the GNU Library General
COPYING:Public License instead of this License.
README.markdown:Read them carefully, as they tell you what this is all about, explain how to install the
README.markdown:  * They are distributed under the GNU General Public License - see the accompanying COPYING file for more details. 
...

I note that I do not get the standard input notification. This suggests me that cat COPYING is extraneous here.

Masi
It seems that the `cat` -part is completely ignored by the command #2.
Masi
Yes: when `grep` is given file names to process, it does not read standard input too (unless the pseudo-filename '`-`' is given, or `/dev/stdin` is used as a file name, or `/dev/fd/0`).
Jonathan Leffler
grep only reads from stdin if there are NO file arguemts. So with #2, the output of cat is sompletely ignored.
Chris Dodd
+1  A: 

Emacs has grep interface (M-x grep, M-x lgrep, M-x rgrep). If you ask Emacs to search for foo in the current directory, then Emacs calls grep and process the grep output and then present you with results with clickable links. Clickable links, just like Google.

What Emacs does is that it passes two options to grep: -n (show line number) and -H (show filenames even if only one file. the point is consistency) and then turn the output into clickable links.

In general, consistency is good for being a good API, but consistency conflicts with DWIM.

When you directly use grep, you want DWIM, so you don't pass -H.

RamyenHead