I am working on an ancient UNIX whose grep lacks the -r/--recursive option.

I need to find an error that our application is causing, but I do not know which log file our application is writing errors to. However, I do know that the log file is somewhere in /opt. So I want to find FooErrorMessage under /opt in *.log. Here's what I tried:

find /opt | xargs grep FooErrorMessage

-- but this does not work, and I don't know where to specify that I just want *.log files in the command.


You're just trying to find all log files under /opt and search them for somethnig_I_am_looking_for right? Why not:

find /opt -name '*.log' | xargs grep something


find /opt | grep .log | xargs grep something


Oh, and since I can't figure out how to comment on the other answers: be careful with *.log as the shell will interpret that as globbing, and match all files in the current directory that end in .log . You should use either \*.log or '*.log'

  • \\*.log or "*.log" – dotjoe Jul 30 '09 at 21:32
  • 4
    dotjoe - be careful with double-quotes. The shell interprets stuff inside double quotes. Single quotes prevent interpretation. – atk Jul 31 '09 at 1:30

Beware of filenames with spaces in them, as it is allowed by Unix; xargs will choke on them. Use find /opt -name '*.log' ... -print0 | xargs -0 grep ..., these options are meant to go together.

Also, grep or your shell might have a limited number of arguments, and the list of files returned by find might exceed that. Use the -n number option of xargs to run grep by chunks of number files.

  • +1 for 'find ... -print0 | xargs -0 ...'. The operating system will limit the total length of the arguments (and the size of the environment also comes out of the same space - so lots of environment variables reduces the number of arguments you can use), but xargs should be attuned to the o/s limit and not create overlong argument lists. Certainly, I don't recall that being a problem ever. – Jonathan Leffler Jul 31 '09 at 5:04

do you have perl?

try -- http://betterthangrep.com/

  • I use Ack every day. I especially like the smart-casing option. – koenigdmj Jul 31 '09 at 3:01

find /opt -type f -name *.log -print | xargs grep 'something_I_am_looking_for'

  • You need quotes around '*.log' to be safe. (And, as written, you do not need quotes around 'something_I_am_looking_for', but it is likely better to include them than omit them - certainly in general. – Jonathan Leffler Jul 31 '09 at 5:01

Apart from adding the "-name '*.log'", try adding -n1 to xargs.

Maybe your ancient grep can't take multiple input files, so -n1 will run grep for each of those files, instead of passing them as arguments at once


You can also do this with the exec option to find instead of xargs

find /opt -exec grep "thing you are looking for" {} \;

  • That launches a command for each file found - that gets expensive by comparison with using xargs. – Jonathan Leffler Jul 31 '09 at 5:05

GNU grep has its own “recurse” option:

 grep -R foo /path/to/directory

To grep files of a particular pattern, you’re best off with find and xargs:

 find /path/to/directory -name \*.log -print0 | xargs -0 grep foo
find /opt -name *.log | xargs grep yourstring 

Unless you have subdirectories that are many levels deep, grep *, grep / and grep //* is easy to remember and hard to type wrong...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy