# Basic grep question.



## Alain De Vos (May 11, 2021)

Following simple problem.
Find all files ending on ".txt" in the current directory tree and subdirectories, which contain the word "hello", and print their names.
Can it be done with grep or do you need , find,xargs,grep ?


----------



## covacat (May 11, 2021)

grep -rl hello .|grep \\.txt$
 but find is better
find . -iname \*.txt -print0 |xargs -0 grep -l hello

the 1st command will search in all files regardless of the extension and then filter only txt files


----------



## VladiBG (May 11, 2021)

`grep -r -l hello *.txt`


----------



## covacat (May 11, 2021)

VladiBG said:


> `grep -r -l hello *.txt`


that does not work (wildcards are expanded by the shell) 

[09:54:01] [box]/usr/src$grep -r include *.c
grep: *.c: No such file or directory


----------



## VladiBG (May 11, 2021)

It works for me in csh


----------



## Alain De Vos (May 11, 2021)

Vladibg, not for me with csh. The expansion is only in the current directory.


----------



## ralphbsz (May 11, 2021)

Alain De Vos said:


> Find all files ending on ".txt" in the current directory tree and subdirectories, ...


Grep can't help with the list of files. Grep is a program, and it is passed a list of files by whatever executes it. Typically that is a shell. Most shells only have a mechanism for glob expansion in a directory, and in enumerated lists of subdirectories. So you can do "grep *.txt" for the current directory, "grep *.txt foo/*.txt" to add all text files in subdirectory foo, or "grep *.txt */*.txt" to add all text file in all subdirectories. But what that does not cover is recursion: It will not find foo/bar/*.txt, nor foo/bar/blatz/... and so on. I vaguely remember that there was one shell that used "**" to stand for "all subdirectories recursively down", but I don't remember which one.

So if you want to recurse infinitely far down, you'll have to use something like find (and perhaps xargs). Personally, I like the "find . -name \*.txt -print0 | xargs -0 grep -l hello" idiom more intelligible than "find . -name \*.txt -exec fgrep -l hello {}", but that's a question of taste.


----------



## covacat (May 11, 2021)

xargs is  better than exec because the number of spawned children is (sometimes a lot) less
and you can control this with xargs -n


----------



## VladiBG (May 11, 2021)

`grep --include="*.txt" -r -l hello .`


----------



## ralphbsz (May 11, 2021)

Seriously, I think VladiBG is right: Looking at the man page for grep, it can recurse down directories with "-r", and it has an include switch to select files when running on whole directories. So it has "find" sort of built in. Didn't know that.


----------

