There are several valid answers here, I would like to compile a comprehensive answer along with mine to make this post easier to read:
Root Cause
$i = 'D:\Texts1';
when used as a regex pattern, "\" should be escaped - what the regex engine want is some ultimate format like: D:\\Texts1. So this doesn't work, however, there are at least 4 different ways to build this format as listed below.
Also to notice, when ' is used as delimiter for match or substitution statement, variable interpolation will be disabled, which renders $filename =~ s'$i'$o'g; almost useless. so first step, change it to use / or {}
Solution 1
use quotemeta, this will effectively escape the "\":
$filename = 'D:\Texts1\text1';
$i = quotemeta('D:\Texts1');
$o = 'D:\Texts2';
$filename =~ s/$i/$o/g;
Solution 2
use \Q .. \E, which has similar effects as quotemeta:
$filename = 'D:\Texts1\text1';
$i = 'D:\Texts1';
$o = 'D:\Texts2';
$filename =~ s/\Q$i\E/$o/g; # or s/\Q$i/$o/g also works
Solution 3
escape the "\" in the string explicitly, and use qr to quote the string as regex pattern.
$filename = 'D:\Texts1\text1';
$i = qr 'D:\\Texts1';
$o = 'D:\Texts2';
$filename =~ s/$i/$o/g;
Solution 4
escape to the extent that the string is ready for regex:
$filename = 'D:\Texts1\text1';
$i = 'D:\\\\Texts1';
$o = 'D:\Texts2';
$filename =~ s/$i/$o/g;