Using just grep and sed, how do I replace all occurrences of:
a.example.com with
b.example.com within a text file under the /home/user/ directory tree recursively finding and replacing all occurrences in all files in sub-directories as well.
Try this:
find /home/user/ -type f | xargs sed -i 's/a\.example\.com/b.example.com/g' In case you want to ignore dot directories
find . \( ! -regex '.*/\..*' \) -type f | xargs sed -i 's/a\.example\.com/b.example.com/g' Edit: escaped dots in search expression
-name 'pattern' - where "pattern" might be like "domainlist*" - something that narrows down the search.-print0 and -0 on the find and xargs commands respectively.Try this:
grep -rl 'SearchString' ./ | xargs sed -i 's/REPLACESTRING/WITHTHIS/g' grep -rl will recursively search for the SEARCHSTRING in the directories ./ and will replace the strings using sed.
Ex:
Replacing a name TOM with JERRY using search string as SWATKATS in directory CARTOONNETWORK
grep -rl 'SWATKATS' CARTOONNETWORK/ | xargs sed -i 's/TOM/JERRY/g' This will replace TOM with JERRY in all the files and subdirectories under CARTOONNETWORK wherever it finds the string SWATKATS.
l flag do in -rl ? Cause it's not working without it :)-l prints the path to each file containing text that matches the pattern.On macOS, none of the answers worked for me. I discovered that was due to differences in how sed works on macOS and other BSD systems compared to GNU.
In particular BSD sed takes the -i option but requires a suffix for the backup (but an empty suffix is permitted)
grep version from this answer.
grep -rl 'foo' ./ | LC_ALL=C xargs sed -i '' 's/foo/bar/g' find version from this answer.
find . \( ! -regex '.*/\..*' \) -type f | LC_ALL=C xargs sed -i '' 's/foo/bar/g' Don't omit the Regex to ignore . folders if you're in a Git repo. I realized that the hard way!
That LC_ALL=C option is to avoid getting sed: RE error: illegal byte sequence if sed finds a byte sequence that is not a valid UTF-8 character. That's another difference between BSD and GNU. Depending on the kind of files you are dealing with, you may not need it.
For some reason that is not clear to me, the grep version found more occurrences than the find one, which is why I recommend to use grep.
I know this is a really old question, but...
@vehomzzz's answer uses find and xargs when the questions says explicitly grep and sed only.
@EmployedRussian and @BrooksMoses tried to say it was a dup of awk and sed, but it's not - again, the question explicitly says grep and sed only.
So here is my solution, assuming you are using Bash as your shell:
OLDIFS=$IFS IFS=$'\n' for f in `grep -rl a.example.com .` # Use -irl instead of -rl for case insensitive search do sed -i 's/a\.example\.com/b.example.com/g' $f # Use /gi instead of /g for case insensitive search done IFS=$OLDIFS If you are using a different shell, such as Unix SHell, let me know and I will try to find a syntax adjustment.
P.S.: Here's a one-liner:
OLDIFS=$IFS;IFS=$'\n';for f in `grep -rl a.example.com .`;do sed -i 's/a\.example\.com/b.example.com/g' $f;done;IFS=$OLDIFS Sources:
% that isn't common in URLs so you don't have to escape all the slashes.We can try using the more powerful ripgrep as
rg "BYE_BYE_TEXT" ./ --files-with-matches | xargs sed -i "s/BYE_BYE_TEXT/WELCOME_TEXT/g" Because ripgrep is good at finding and sed is great at replacing.
rg keeps using backslashes, sed does not like that (mostly omits them since none matches to an escape code in my case, I guess) and fails with No such file or directoy. I could sed the backlashes to slashes but an rg options would make things easier in general. For now I use rg "inpattern" ./ --files-with-matches | sed "s|\\\|/|g" | xargs sed -i -b "s/inpattern/outpattern/g" - (-b/binary mode to keep your line endings as they are).Try this command:
/home/user/ directory - find ./ -type f \ -exec sed -i -e 's/a.example.com/b.example.com/g' {} \; The command below will search all the files recursively whose name matches the search pattern and will replace the string:
find /path/to/searchdir/ -name "serachpatter" -type f | xargs sed -i 's/stringone/StrIngTwo/g'
Also if you want to limit the depth of recursion you can put the limits as well:
find /path/to/searchdir/ -name "serachpatter" -type f -maxdepth 4 -mindepth 2 | xargs sed -i 's/stringone/StrIngTwo/g'