Bash Grep Subdirectories (Recursively)

last updated in Categories

How do I recursively grep through all sub-directories and find files containing given text / string or words?

You can use the -r option to recursively grep through all sub-directories and find text. The syntax is as follows:

grep -r "text" /path/to/dir

In this example, search for an IP in through all /etc/ and all its sub-directories:

grep -r "" /etc/

Search in any case:

grep -ri "letters" /home/vivek/data

Use the -l switch to display only the names of files in which the text occurs:

grep -lri "foo" /data

Posted by: Vivek Gite

The author is the creator of nixCraft and a seasoned sysadmin, DevOps engineer, and a trainer for the Linux operating system/Unix shell scripting. Get the latest tutorials on SysAdmin, Linux/Unix and open source topics via RSS/XML feed or weekly email newsletter.

4 comment

  1. Grep does allow recursive search, but only if you don’t specify the files you are looking for. For example:
    grep -r ‘ActiveServer’ . works, but outputs a lot of noise (like log and binary files)

    grep -r ‘ActiveServer’ *.java will tell something like:
    “zsh: no matches found: *.java”

    A “quick and dirty” way to solve the problem:
    grep -r ‘ActiveServer’ . | grep ‘.java:’
    This still might output some non-java entries.
    But this doesn’t ():
    grep -rl ‘ActiveServer’ . | grep ‘.java’

    I usually run this command and a separate terminal tab (or window).

  2. When I want to grep over files with a specific extension in a file tree I do it combining it with “find”:
    $ find . -name \*.java | xargs grep ‘ActiveServer’

  3. See, this is why sometimes *nix really sucks. For over 15 years I’ve used the Borland version of grep on Windows which does recursive searches through subdirectories in files specified by wildcard filenames, and it works fine, intuitively and logically.

    For example, to search all .css files in the branch of a project for the word “header”, you can type:

    grep -r “header” *.css

    …and grep recurses through all subdirectories only searching files that match *.css
    …no muss, no fuss, no screwing around with bizarre tool things and contorted syntax

    But it’s not *nix grep’s fault — the fault is the design of the *nix file system and command line expansion. The expansion of wildcard filenames inline rather than passing the wildcard descriptor to the programs for traversal is one of the most doofus features of *nix. I don’t know how many programmers have been burned by this “feature” when they typed something like:

    compile *.c

    and the compile broke because the inline expanded filenames broke the piping system. This rinky-dink way of working is fine for toy programs and projects, but it’s a pain in the butt when you try to do anything of size. A large real project could have on the order of 50-100 libraries, each with 10-1000 program files. The make facility was created to get around this limitation.

    Whereas on the old PDP-10, with the OS and programs running in less than 10 megabytes of memory, you could type

    compile *.c

    and it would just do it. You could also type

    link *.c
    execute *.c

    and it was smart enough to look at the file times and dates, compile what it needed to, link object modules and libraries, and even begin execution, all without need for a make facility.

    I use both *nix and MS operating systems, they both have good and bad things about them. Someday someone should fix that wildcard file situation with some future version of *nix, but I think it’s gonna take a complete re-roll of the OS.

  4. Of course, you could just learn how to use it the shell and escape the wildcards when you specifically don’t want them .

    Still, have a question? Get help on our forum!