Find and Replace string in all files recursive using grep and sed [duplicate] Find and Replace string in all files recursive using grep and sed [duplicate] bash bash

Find and Replace string in all files recursive using grep and sed [duplicate]


As @Didier said, you can change your delimiter to something other than /:

grep -rl $oldstring /path/to/folder | xargs sed -i s@$oldstring@$newstring@g


grep -rl $oldstring . | xargs sed -i "s/$oldstring/$newstring/g"


The GNU guys REALLY messed up when they introduced recursive file searching to grep. grep is for finding REs in files and printing the matching line (g/re/p remember?) NOT for finding files. There's a perfectly good tool with a very obvious name for FINDing files. Whatever happened to the UNIX mantra of do one thing and do it well?

Anyway, here's how you'd do what you want using the traditional UNIX approach (untested):

find /path/to/folder -type f -print |while IFS= read -r filedo   awk -v old="$oldstring" -v new="$newstring" '      BEGIN{ rlength = length(old) }      rstart = index($0,old) { $0 = substr($0,rstart-1) new substr($0,rstart+rlength) }      { print }   ' "$file" > tmp &&   mv tmp "$file"done

Not that by using awk/index() instead of sed and grep you avoid the need to escape all of the RE metacharacters that might appear in either your old or your new string plus figure out a character to use as your sed delimiter that can't appear in your old or new strings, and that you don't need to run grep since the replacement will only occur for files that do contain the string you want. Having said all of that, if you don't want the file timestamp to change if you don't modify the file, then just do a diff on tmp and the original file before doing the mv or throw in an fgrep -q before the awk.

Caveat: The above won't work for file names that contain newlines. If you have those then let us know and we can show you how to handle them.