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

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


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.


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


If your sed(1) has a -i option, then use it like this:

for i in *; do  sed -i 's/foo/bar/' $idone

If not, there are several ways variations on the following depending on which language you want to play with:

ruby -i.bak -pe 'sub(%r{foo}, 'bar')' *perl -pi.bak -e 's/foo/bar/' *