Bash Commands – How to Act on the Results of the Locate Command

bashcommand linegreplocateUbuntu

I'm trying to find where check_dns is defined in nagios' commands.cfg file, although there are quite a few files.

I know I could run something like find / -name "command.cfg" -exec grep check_dns {} \; to search for matches, but if possible I would like to use locate since it is an indexed copy and much faster.

When I run locate commands.cfg I get the following results:

/etc/nagios3/commands.cfg
/etc/nagiosgrapher/nagios3/commands.cfg
/usr/share/doc/nagios3-common/examples/commands.cfg
/usr/share/doc/nagios3-common/examples/template-object/commands.cfg
/usr/share/nagiosgrapher/debian/cfg/nagios3/commands.cfg
/var/lib/ucf/cache/:etc:nagiosgrapher:nagios3:commands.cfg

Is it possible to run locate and pipe it to an inline command like xargs or something so that I can grep each of the results? I realize this can be done with a for loop but I'm looking to pick up some bash-fu / shell-fu here more than how to do it for this specific case.

Best Answer

Yes, you can use xargs for this.

For example a simple:

$ locate commands.cfg | xargs grep check_dns

(When grep sees multiple files it searches in each one and enables filename printing along matches.)

Or you can explicitly enable filename printing via:

$ locate commands.cfg | xargs grep -H check_dns

(Just in case one grep is called only with 1 argument by xargs)

For programs that only accept one filename argument (unlike grep) you can restrict the number of supplied arguments like this:

$ locate commands.cfg | xargs -n1 grep check_dns

That does not print the names of files where matched lines are from.

The result is equivalent to:

$ locate commands.cfg | xargs grep -h check_dns

With a modern locate/xargs you can also protect against whitespace issues:

$ locate -0 commands.cfg | xargs -0 grep -H check_dns

(By default whitespace separates input of xargs - which is of course a problem when your filenames contain whitespace ...)

Related Question