Replace very long string in files recursively

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?

Asked By: apparat

||

Yes, you should be able to use the -f option to specify a file containing a [list of] expression[s]

   -f script-file, --file=script-file

          add the contents of script-file to the commands to be executed

However you will still need to escape any special characters (AFAIK there is no sed equivalent of grep’s --fixed-strings) – if perl is available on your system, you may wish to look at using that instead, with the Q...E quoted string modifiers.

Answered By: steeldriver

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}/' {} +
Categories: Answers Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.