POSIX-compliant recursive grep with no errors for inaccessible directories

findgrep

What script would allow me to grep a keyword and print the filename containing the keyword inside the file content, for example 'Carhart' inside all .sas files in all subdirectories? I tried something like the following but it doesn't work:

(find . -name '*.sas' -prune -type f -exec grep 'Carhart' > /dev/tty) >& /dev/null

The script would satisfy two conditions

  1. It runs on tcsh on Solaris on SPARC-Enterprise, which is certified POSIX
  2. It does not generate 'Permission denied' lines on directories which I have no permission to search and/or read. ( find / -name '*.sas' -prune > /dev/tty ) > & /dev/null

Since ( find / -name '*.sas' -prune > /dev/tty ) > & /dev/null works without reporting permission denied error, how can I modify this simple line to incorporate grep?

Best Answer

To make grep print only the file name, pass the -l option. To search for a substring rather than a regular expression, pass the -F option.

To search recursively for files whose name matches a certain pattern, use find with the -type f and -name PATTERN primaries. Use -exec to invoke grep.

find . -name '*.sas' -type f -exec grep -F -l 'Carhart' {} +

If you want to avoid errors from directories that you aren't allowed to traverse, you can either use -perm, -user and -group to analyze permissions (which is difficult to get right, and won't work if you have ACL), or call test (which is slowed because it's an external program, but is more reliable).

find . -type d ! -exec test -r {} -a -x {} \; -prune -o \
       -name '*.sas' -type f -exec test -r {} \; -exec grep -F -l 'Carhart' {} +