Posted on Leave a comment

Search and Replace in all files within a folder recursively on Linux/Unix

In order to search recursively through directories, looking in all the files for a particular string, then to replace that string with something else (on linux/Unix), these commands should work (Where string1 is the original string and string2 is the replace-string):

[box type=”shadow”]find ./ -type f -exec sed -i ‘s/string1/string2/’ {} \;[/box]

It would have been better to use xargs instead of -exec. Using xargs, you will fork fewer times. For large numbers of files, that means you will be done faster. In other words:

[box type=”shadow”]find ./ -type f | xargs sed -i 's/string1/string2/'[/box]

Instead of editing all files in a directory, you can use the same concept with grep to edit only files containg a certain string. In other words:

[box type=”shadow”]grep -rl matchstring somedir/ | xargs sed -i 's/string1/string2/'[/box]

The trick works fine except for one thing: It only replaces the first instance of string1 it finds in each file. For example if you had 100 instances of string1 in some files, then you would have to run the command 100 times! Also, if you don’t know how many times string1 can be found in the files, then you also don’t know how many times ou have to run the command before everything is replaced.

One Solution:

[box type=”shadow”]grep -rl matchstring somedir/ | xargs sed -i ’s/string1/string2/g’

the g on the edn will replace globally – all instances of string1[/box]

BEWARE:

If any of the files fed through xargs are binary, both sed and perl will change the timestamps of the files that all have the string, binary files or text files, but no changes are made (in at least the one file *I* was looking at at the top of the file directory hierarchy). So filter out binary files.

Another simpler Solution:

use the ‘rpl’ command (apt-get install rpl; yum install rpl):

[box type=”shadow”]rpl -x'.cpp' -x'.h' -pR "old-string" "new-string" *[/box]

or replace directly without prompt

[box type=”shadow”]rpl -x'.cpp' -x'.h' -R "old-string" "new-string" *[/box]

Here, all files with a .cpp or .h suffix wil be searched for an “old-string”. If found the “old-string” is replaced by the “new-string” in all directories recursively.

Another Solution FIY:
The rrep program lets you replace strings in multiple files and also recursively in directories. It also supports regular expressions. The usage is similar to grep.
http://sourceforge.net/projects/rrep/