Like it!

Join us on Facebook!

Like it!

Linux: how to find and replace text in multiple files

Harness the power of grep and sed.

Often times I need to search and replace a string of text across multiple files in my Linux box. After a bit of research I've come up with a nice solution. Assuming that you want to search for the string search through multiple files and replace it with replace, this is the one-liner:

grep -RiIl 'search' | xargs sed -i 's/search/replace/g'

Let me now dissect it and take a quick look at the different tools in use.

grep

grep is a utility for searching for strings through multiple text files. Here I'm invoking it with the following parameters:

  • R — perform a recursive search, also across symbolic links;
  • i — case-insensitive search
  • I — skip binary files. We are working with text, afer all;
  • l — print results as a simple list of file names. This is needed for the next command.

The output of grep is then piped to ...

xargs

This is a little command-line utility that takes what receives in input and passes it as argument to another program. So in this example the output of grep is passed to the next command sed as its argument.

sed

sed is a glorious Unix utility that transforms text. In the current snippet I'm using it to replace text with the following parameters:

  • i — replace in file. Remove it for a dry run mode;
  • s/search/replace/g — this is the substitution command. The s stands for substitute (i.e. replace), the g instructs the command to replace all occurrences.

Fine tuning 1: how to exclude directories while searching

You can add the --exclude-dir=<dir> parameter to grep if you want to skip a specific directory while searching for files. For example, say you want to skip the tests/ directory:

grep -RiIl --exclude-dir=tests 'search' | xargs sed 's/search/replace/g'

Exclude multiple directories by wrapping them into curly braces, like so:

grep -RiIl --exclude-dir={dir1,dir2,dir3} 'search' | xargs sed 's/search/replace/g'

Fine tuning 2: regular expressions

Both grep and sed support regular expressions, so you can search with grep given a specific pattern and then replace the text with sed given another one. Take a look at the grep manual and the sed manual for more information.

Sources

StackOverflow - How to replace a string in multiple files in linux command line

comments
Sam on September 09, 2019 at 10:10
Hi,
Thanks for sharing the tips.
I have tried your command but not succeed.
I found that there should be a dot or file path at the end of grep command.
Cheers,
Sam
Triangles on November 10, 2019 at 15:26
@Sam you're on macOS, right? The -R flag wants the dot (or file path) at the end of grep command: https://apple.stackexchange.com/questions/275373/how-to-make-grep-work-like-in-ubuntu/275379 . Thanks for the input :)
VM on August 04, 2020 at 15:26
Some infos are wrong here, so its normal that people are not able to use it. In particular :
- "-i" option of grep IGNORE case, and don't make it case sensitive as said in the grep man page :
"-i, --ignore-case
Ignore case distinctions in both the PATTERN and the input files." (source : https://linux.die.net/man/1/grep)
"-R" option actually follow symbolic links while "-r" don't which deserve to be mentioned.
Jill Ackerman on October 12, 2020 at 17:44
This worked for me...on Git Bash (Windows)..except I would like it to print a list of changed lines to stnd out, it is listing changed files
Stephane on November 12, 2020 at 12:25
Hi, I'm trying to replace the dates in files by the first date in their corresponding files. But I can't figure out how to use the first one to replace the others :-/
Thanks

The dates correspond to this regex:

([1-2]\d\d\d:(0[1-9]|1[0-2]):(0[1-9]|[1-2]\d|3[0-1]) (0\d|1\d|2[0-3]):[0-5]\d:[0-5]\d)
came in handy on March 17, 2021 at 12:06
thank you
Wesley Chen on January 19, 2022 at 00:45
This post saved my ass. Thanks a lot!
Aaron on May 20, 2022 at 05:20
I copied the above replace command(with the line break) into my folder and it automatically executed the place for 'search' to 'replace' and all my files containing 'search' key word were replaced .....
Ashok Sahu on July 14, 2022 at 13:17
I am found that in this scenario if we use bulk data is good
Manoj on October 27, 2022 at 08:00
It works for me thanks
Scott on June 30, 2023 at 12:37
This is great except if there are spaces in your file names. If you pass a file name with a space in it to xargs, it will be treated as two different files and fail or do something unexpected.

The solution is to have grep list the file names null-terminated (using --null flag) and have xargs split on null instead of space (using -0 flag, that's a zero).

Looks like:

grep -RiIl --null 'search' | xargs -0 sed -i 's/search/replace/g'