Effect of using eval to execute a command as opposed to writing it on the commandline

cmd='date | wc' or cmd="date | wc"
$cmd

If this script is executed, an error is generated. The reason written was that "The execution fails because the pipe is not expanded and is passed to date as an argument". What is meant by expansion of pipe. When we execute date | wc on the command line, it goes fine. then | is not treated as an argument. Why?

If I write

cmd='date | wc' or cmd="date | wc"
eval $cmd

It works. How?

I understand (hopefully) how eval works in 2 passes i.e. the command first gets evaluated and then executed.

The shell has already tokenized the command line and performed any redirection before the variable is expanded.

When you use eval, the expansion is done first, then the shell parses the result.

1 Like

Thanks. I get that since all the special symbols like |,",',; all are evaluated before substitution takes place. Hence, in the case of $cmd, since no specia symbols were initially found, cmd was substituted for "date | wc" and | was taken as an argument to date (as | now has no meaning).

One question though, why do call evaluating the special symbols like | as expanding it? Does it mean that a special code for these symbols is inserted there when they're expanded ?

Also, it seems that there is another function of eval. When there are no substitutions to be made, then eval just removes the special symbols like '' and backslash. Like in the following :

eval echo \\l
eval echo \\\k
eval echo 'h'

I'm using bash shell