Let’s take things step by step:
When you do this:
mycmd='cat $myfile'
You prevent the shell from interpolating $myfile
. Thus:
$ echo $mycmd
cat $myfile
If you want to allow the interpolation, you can use double quotes:
$ mycmd="echo $myfile" #Double quotes!
$ echo "$mycmd"
cat afile.txt
This, of course, freezes the interpretation of $mycmd
when you do an eval
.
$ myfile="afile.txt"
$ mycmd="echo $myfile"
$ echo $mycmd
cat afile.txt
$ eval $mycmd #Prints out afile.txt
$ myfile=bfile.txt
$ eval $mycmd #Still prints out afile.txt and not bfile.txt
Compare this to:
$ myfile="afile.txt"
$ mycmd='cat $myfile' #Single quotes hide $myfile from the shell
echo $mycmd
cat $myfile #Shell didn't change "$myfile", so it prints as a literal
$ eval $mycmd #Prints out afile.txt
$ myfile=bfile.txt
$ eval $mycmd #Now prints out bfile.txt
What you probably want to do is to evaluate the $mycmd
in an echo statement when you echo it:
$ echo $(eval "echo $mycmd")
$ cat afile.txt
$ myfile=bfile.txt
$ echo $(eval "echo $mycmd")
cat bfile.txt