2

I have changed up my director structure and I want to do the following:

  • Do a recursive grep to find all instances of a match
  • Change to the updated location string

One example (out of hundreds) would be:

from common.utils import debug  --> from etc.common.utils import debug

To get all the instances of what I'm looking for I'm doing:

$ grep -r 'common.' ./

However, I also need to make sure common is preceded by a space. How would I do this find and replace?

5
  • egrep is a Solaris command afaikr. Commented Jun 3, 2012 at 1:51
  • 3
    @RobKielty egrep is on at least all gnu systems, short for grep -E (extended regexes, which you actually don't need here) Commented Jun 3, 2012 at 1:55
  • 1
    Also, OP, you want \., not just a .; otherwise it's interpreted as anything but a newline. Commented Jun 3, 2012 at 1:55
  • OP Can you call out exactly the change that you want to do? Will have to figure out the a sed command based on what you need done. Commented Jun 3, 2012 at 2:00
  • 1
    Actually egrep goes way back to Bell Labs original Unix. Commented Jun 3, 2012 at 5:45

3 Answers 3

4

It's hard to tell exactly what you want because your refactoring example changes the import as well as the package, but the following will change common. -> etc.common. for all files in a directory:

sed -i 's/\bcommon\./etc.&/' $(egrep -lr '\bcommon\.' .)

This assumes you have gnu sed available, which most linux systems do. Also, just to let you know, this will fail if there are too many files for sed to handle at one time. In that case, you can do this:

egrep -lr '\bcommon\.' . | xargs sed -i 's/\bcommon\./etc.&/'

Note that it might be a good idea to run the sed command as sed -i'.OLD' 's/\bcommon\./etc.&/' so that you get a backup of the original file.

Sign up to request clarification or add additional context in comments.

Comments

1

If your grep implementation supports Perl syntax (-P flag, on e.g. Linux it's usually available), you can benefit from the additional features like word boundaries:

$ grep -Pr '\bcommon\.'

By the way:

grep -r tends to be much slower than a previously piped find command as in Rob's example. Furthermore, when you're sure that the file-names found do not contain any whitespace, using xargs is much faster than -exec:

$ find . -type f -name '*.java' | xargs grep -P '\bcommon\.'

Or, applied to Tim's example:

$ find . -type f -name '*.java' | xargs sed -i.bak 's/\<common\./etc.common./'

Note that, in the latter example, the replacement is done after creating a *.bak backup for each file changed. This way you can review the command's results and then delete the backups:

$ find . -type f -name '*.bak' | xargs rm

If you've made an oopsie, the following command will restore the previous versions:

$ find . -type f -name '*.bak' | while read LINE; do mv -f $LINE `basename $LINE`; done

Of course, if you aren't sure that there's no whitespace in the file names and paths, you should apply the commands via find's -exec parameter.

Cheers!

3 Comments

You don't need -P for simple word boundaries, but they are \< for left and \> for right in egrep.
Thank you. That's what I figured after reading Tim's post. I tried it immediately in my vi. It worked, of course. Then I asked myself what I have done all those years. Now I don't know whether I should be happy about this new-to-me feature or crying about all the wasted time...
@tripleee egrep also supports \b for word boundaries. \< and \> are just edge-specific versions of \b.
1

This is roughly how you would do it using find. This requires testing

 find . -name \*.java -exec sed "s/FIND_STR/REPLACE_STR/g" {}

This translates as "Starting from the current directory find all files that end in .java and execute sed on the file (where {} is a place holder for the currently found file) "s/FIND_STR/REPLACE_STR/g" replaces FIND_STR with REPLACE_STR in each line in the current file.

1 Comment

Force of habit from vi. I removed it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.