Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Command line: search and replace in all filenames matched by grep

I'm trying to search and replace a string in all files matched by grep:

grep -n 'foo' * will give me output in the form:

[filename]:[line number]:[text] 

For each file returned by grep, I'd like to modify the file by replacing foo with bar.

like image 416
Michael Kristofik Avatar asked Jan 22 '09 22:01

Michael Kristofik


2 Answers

This appears to be what you want, based on the example you gave:

sed -i 's/foo/bar/g' * 

It is not recursive (it will not descend into subdirectories). For a nice solution replacing in selected files throughout a tree I would use find:

find . -name '*.html' -print -exec sed -i.bak 's/foo/bar/g' {} \; 

The *.html is the expression that files must match, the .bak after the -i makes a copy of the original file, with a .bak extension (it can be any extension you like) and the g at the end of the sed expression tells sed to replace multiple copies on one line (rather than only the first one). The -print to find is a convenience to show which files were being matched. All this depends on the exact versions of these tools on your system.

like image 142
MattJ Avatar answered Oct 02 '22 17:10

MattJ


Do you mean search and replace a string in all files matched by grep?

perl -p -i -e 's/oldstring/newstring/g' `grep -ril searchpattern *` 

Edit

Since this seems to be a fairly popular question thought I'd update.

Nowadays I mostly use ack-grep as it's more user-friendly. So the above command would be:

perl -p -i -e 's/old/new/g' `ack -l searchpattern` 

To handle whitespace in file names you can run:

ack --print0 -l searchpattern | xargs -0 perl -p -i -e 's/old/new/g' 

you can do more with ack-grep. Say you want to restrict the search to HTML files only:

ack --print0 --html -l searchpattern | xargs -0 perl -p -i -e 's/old/new/g' 

And if white space is not an issue it's even shorter:

perl -p -i -e 's/old/new/g' `ack -l --html searchpattern` perl -p -i -e 's/old/new/g' `ack -f --html` # will match all html files 
like image 22
armandino Avatar answered Oct 02 '22 18:10

armandino