views:

165

answers:

7

I have a hierarchy of directories containing many text files. I would like to search for a particular text string every time it comes up in one of the files, and replace it with another string. For example, I may want to replace every occurrence of the string "Coke" with "Pepsi". Does anyone know how to do this? I am wondering if there is some sort of Bash command that can do this without having to load all these files in an editor, or come up with a more complex script to do it.

I found this page explaining a trick using sed, but it doesn't seem to work in files in subdirectories.

+11  A: 

Use sed in combination with find. For instance:

find . -name "*.txt" | xargs sed -i s/Coke/Pepsi/g

or

find . -name "*.txt" -exec sed -i s/Coke/Pepsi/g {} \;

(See the man page on find for more information)

Yann Ramin
also,if you're using a combination of `find` and `xargs`, particularly in a script, it's always best to use `find -print0` and `xargs -0`, to guard against files with spaces in their names
Martin DeMello
I tried your first suggestion and it worked. Thank you.
mikez302
@mikez302: Please take Martin's comment into account. `xargs` is often not required and should usually be used with the `-0` switch. The second solution is much better.
Philipp
`find` also has the option to spawn only a single process for all results if you use `+` instead of `;` as the delimiter to `-exec`: `find . -name '*.txt' -exec sed -i 's/Coke/Pepsi/g' '{}' +`
janmoesen
+2  A: 

I usually do it in perl. However watch out - it uses regexps which are much more powerful then normal string substitution:

% perl -pi -e 's/Coke/Pepsi/g;' $filename

EDIT I forgot about subdirectories

% find ./ -exec perl -pi -e 's/Coke/Pepsi/g;' {} \;
Maciej Piechotka
+2  A: 

IMO, the tool with the easiest usage for this task is rpl:

rpl -R Coke Pepsi .

(-R is for recursive replacement in all subdirectories)

Chris Lercher
Dennis Williamson
@Dennis: Thanks! I should have thought about adding at least one of them.
Chris Lercher
+3  A: 

Combine sed with find like this:

find . -name "file.*" -exec sed -i 's/Coke/Pepsi/g' {} \;
rmarimon
+3  A: 

find . -type f -exec sed -i 's/old-word/new-word/g' {} \;

Evaggelos Balaskas
+2  A: 

you want a combination of find and sed

fuzzy lollipop
A: 

You may also:

Search & replace with find & ed

http://codesnippets.joyent.com/posts/show/2299

(which also features a test mode via -t flag)

eddie