2

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.

9 Answers 9

5

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

or

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'

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

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
  • +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. Jul 31, 2009 at 5:04
3

do you have perl?

try -- http://betterthangrep.com/

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

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

1
  • 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. Jul 31, 2009 at 5:01
1

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

1

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

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

1
  • That launches a command for each file found - that gets expensive by comparison with using xargs. Jul 31, 2009 at 5:05
1

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
0
find /opt -name *.log | xargs grep yourstring 
0

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

You must log in to answer this question.