What's the difference between grep -r and -R

"Being on the command line" refers to the arguments passed to grep. If you give a symbolic link as an argument to grep -r it follows it. However, if grep -r encounters a symbolic link while traversing a directory it does not follow it (in contrast to grep -R which does).

Imagine you have a directory with a bunch of files in it, including one containing a symbolic link to .. (the parent directory):

$ ls -la
total 0
drwxr-xr-x 2 aw aw 47 Mar 31 16:05 .
drwxr-xr-x 3 aw aw 27 Mar 31 16:04 ..
-rw-r--r-- 1 aw aw  0 Mar 31 16:05 bar
-rw-r--r-- 1 aw aw  0 Mar 31 16:05 baz
lrwxrwxrwx 1 aw aw  2 Mar 31 16:04 foo -> ..
-rw-r--r-- 1 aw aw  0 Mar 31 16:05 quux
$

Then,

  • grep -r foobar . will only grep the files inside this directory,
  • grep -r foobar foo will grep the files in the parent directory (..) (following the symlink given as an argument),
  • grep -R foobar . will also grep the files in the parent directory (following the symlink not given as an argument but found while traversing the current directory).

If you check also man grep:

-r, --recursive

Read all files under each directory, recursively, following symbolic links only if they are on the command line. This is equivalent to the -d recurse option.

-R, --dereference-recursive

Read all files under each directory, recursively. Follow all symbolic links, unlike -r.

See an example:

We create in /test a file with the content

$ cat /test/a
Ping info
Hello

And then I create a symlink:

$ ln -s /test/a /test/dir/b

So that it looks like:

$ ls -l /test/dir
b -> ../a

And now we grep:

$ grep -r Ping /test/dir/*     #does NOT follow the symlink to ../a
a:Ping info

$ grep -R Ping /test/dir/*     #DOES follow the symlink to ../a
a:Ping info
dir/b:Ping info

Tags:

Grep