11

In Windows, if I wanted to find a string across all files in all subdirectories, I would do something like

findstr /C:"the string" /S *.h

However, in Linux (say, Ubuntu) I have found no other way than some piped command involving find, xargs, and grep (an example is at this page: How can I recursively grep through sub-directories?). However, my question is different: is there any single, built-in command that works through this magic, without having to write my shell script?

0

5 Answers 5

24

GNU grep allows searching recursively through subdirectories:

grep -r --include='*.h' 'the string' .
5
  • I tried this exact command line in Ubuntu but get "grep: invalid option -- 'M'" although I can't see any 'M' anywhere... puzzling Feb 14, 2011 at 14:45
  • @Guido Works fine over here
    – phunehehe
    Feb 14, 2011 at 15:15
  • In a suggested edit TomasG recommends changing the last * to '*': "Quoting the last wildcard is needed to avoid errors when some filename starts with -" Feb 14, 2011 at 16:07
  • In a strange twist of events, it now works for me too, as entered in the original answer. Thanks! Feb 14, 2011 at 16:34
  • 1
    @Guido: Your problem may have been due to a file in the current directory called -Msomething, or to a GREP_OPTIONS setting. Feb 14, 2011 at 20:43
2

grep -r searchpattern /path/to/start/in

Where /path/to/start/in/ can be just "." for the current directory.

1

No. find -name \*.h -print0 | xargs -0 grep -l 'the regex' is as magic as it gets.

2
  • 1
    GNU grep has the common cases built-in with its -r option. No need for the heavy artillery. Feb 14, 2011 at 20:44
  • 4
    xargs adds just noise. Use find -name \*.h -execdir grep -l 'the regex {} + Apr 15, 2011 at 22:47
1

To find string from given directory use below command

find <fullDirectoryPath> -name '*' -exec grep -l '<StringToFind>' {} \;

For example:

find /apps_bev/apps/xfer/export/02210 -name '*' -exec grep -l '38221000001032' {} \;
2
  • 1
    grep can take more than one file as arguments, so you should use + instead of \; to avoid running one grep invocation per file which is quite inefficient. Nov 20, 2019 at 7:39
  • 1
    Note that -name '*' restricts to files whose name is valid text in the current locale (in some find implementations at least), but the other directory components may still contain sequences of bytes that don't form valid characters. If your intention with that -name '*' was to make sure the output is valid text (by omiting the files with improper names), you'd rather use find ... ! -name '*' -prune -o -exec grep ... {} +, which would also stop find from descending into directories with improper names. Nov 20, 2019 at 7:44
0

is there any single, built-in command that works through this magic ... ?

To be pedantic, no, you cannot assume such a command exists.

There are many different implementations of Unix, and each has its different quirks. POSIX, the common denominator (and closest thing to a standard across Unices) does not specify such an option for grep.

As mentionned in other answers, GNU's implementation of grep has a non-standard option that does what you want. While this particular implementation might be common on Linux systems, you cannot assume its availability on any Unix, even some Linux systems.

Finally, I should mention that it is the Unix philosophy to favor the combination of several primitive programs, over the use of one big monolithic executable attempting to do everything at once.

In your case, crawling the file system and matching regexp in a stream are two separate tasks. It is only normal to treat each in a separate program.

You must log in to answer this question.

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