How to find files containing two strings in different lines

findgrep

A real example is: I have a Python file util.py, and I changed one of the function name from foo to bar. There might be other files using foo as function name and they are irrelevant.

I want to update all the Python files in the project from foo to bar. So I would like to do a search on files for imports such as:

import project.path.util

or

from project.path.util import foo

and any calls to foo such as one starting with:

foo(

The solution has to be whitespace tolerant.
I can search each of them using grep but I am uncertain about the combined search. Any suggestions will be appreciated.

Best Answer

With GNU tools:

grep -rlZ --include='*.py' -e 'import project.path.util' \
                           -e 'from project.path.util import.*\bfoo\b' . |
  xargs -r0 sed -i 's/\bfoo\b/bar/g'

This works by asking grep to

  1. search recursively (-r)
  2. outputting names of matching files (-l)
  3. separated by NUL instead of LF (-Z)
  4. considering only files ending in '.py' (--include='*.py')

and asking sed to perform the replacement in-place (-i) in all matching files, if there are any (xargs -r).

Related Question