Please see the below session transcript:
$ mkdir temp
$ cd temp/
$ touch file{1..5}
$ ls
file1 file2 file3 file4 file5
$ SRC=file; TGT=ram
$ for f in file* ; do mv $f ${f/$SRC/$TGT} ; done
$ ls
ram1 ram2 ram3 ram4 ram5
$ PAT=ram/file
$ for f in ram* ; do mv $f ${f/$PAT} ; done
mv: 'ram1' and 'ram1' are the same file
mv: 'ram2' and 'ram2' are the same file
mv: 'ram3' and 'ram3' are the same file
mv: 'ram4' and 'ram4' are the same file
mv: 'ram5' and 'ram5' are the same file
Why does the pattern substitution work if I provide SRC and TGT as separate variables and not if I provide them as a single variable PAT?
My understanding is that substitutions are processed inside out, and so the string within the outer set of braces i.e. f/$SRC/$TGT or f/$PAT should be equally processed to f/file/ram or f/ram/file, which is then again processed to give the actual new file name. But apparently this is not done so…
I'm using Bash 4.4.18 on Kubuntu Bionic LTS with latest updates.
evalto work around that:eval "mv \$f \${f/$PAT}". Would be great to include this (or other possible solutions) in your answer. – filbranden Jun 06 '19 at 13:02evalsafely is tricky enough that I'd rather not. This is pretty much a non-problem - I don't see any good reason why anyone would want to do this. Even if, for some weird reason, somebody hadpattern/stringin a variable, splitting those out into separate variables is easy enough that there's no good reason to useevaleither. – muru Jun 06 '19 at 13:38