Bash – Replace very long string in files recursively

bashreplacesearchstring

I have a very long and complex string in many files and I want to remove/replace it recursively. The string contains many slashes, backslashes and spaces and any kind of special signs. How do I do that? A simple find + sed combination wouldn't work because of all the special signs in it which I hardly can escape.

Would it be possible to write the search string to a file and use this as input for a search & replace command?

Best Answer

I assume that the string can contain any character except newlines and null bytes. You can quote the string for use as a sed pattern. The characters $*./[\^ need to be preceded by a backslash. In the replacement text, you need to quote the characters \&/.

regexp=$(printf %s "$old" | sed 's:[$*./\[^]:\\&:g')
replacement=$(printf %s "$new" | sed 's:[\&/]:\\&:g')
sed -e "s/$regexp/$replacement/g"

If you have Perl available, it's simpler.

export old new
perl -pe 's/\Q$ENV{old}/$ENV{new}/'

To act on all the files in the current directory and its subdirectories recursively:

regexp=$(printf %s "$old" | sed 's:[$*./\[^]:\\&:g')
replacement=$(printf %s "$new" | sed 's:[\&/]:\\&:g')
export regexp replacement
find . -type f -exec sh -c 'for x; do sed -e "s/$regexp/$replacement/g" <"$x" >"$x.new" && mv "$x.new" "$x"; done' _ {} +

or

export old new
find . -type f -exec perl -i -pe 's/\Q$ENV{old}/$ENV{new}/' {} +