Eu assumo que a string pode conter qualquer caractere, exceto newlines e null bytes. Você pode citar a string para usar como um padrão sed. Os caracteres $*./[\^
precisam ser precedidos por uma barra invertida. No texto de substituição, você precisa citar os caracteres \&/
.
regexp=$(printf %s "$old" | sed 's:[$*./\[^]:\&:g')
replacement=$(printf %s "$new" | sed 's:[\&/]:\&:g')
sed -e "s/$regexp/$replacement/g"
Se você tem o Perl disponível, é mais simples.
export old new
perl -pe 's/\Q$ENV{old}/$ENV{new}/'
Para atuar em todos os arquivos no diretório atual e em seus subdiretórios recursivamente:
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' _ {} +
ou
export old new
find . -type f -exec perl -i -pe 's/\Q$ENV{old}/$ENV{new}/' {} +