Join us on Facebook!
— Written by Triangles on August 17, 2019 • updated on November 10, 2019 • ID 75 —
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 searchI
— 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. 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'
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.
StackOverflow - How to replace a string in multiple files in linux command line
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
- "-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.
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)
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'