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.
eval
to 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:02eval
safely 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/string
in a variable, splitting those out into separate variables is easy enough that there's no good reason to useeval
either. – muru Jun 06 '19 at 13:38