What is eval?
eval is a shell command which is usually implemented as a builtin.
In POSIX it is listed as part of "2.14. Special Built-In Utilities" at the entry "eval".
What builtin means is:
The term "built-in" implies that the shell can execute the utility directly and does not need to search for it.
What does it do?
In simple terms: makes an input line to be parsed twice.
How does it do that?
The shell has a sequence of steps that it follows to "process" a line.
From the POSIX description:
2.1 Shell Introduction
- The shell reads its input ....
- The shell breaks the input into tokens: words and operators
- The shell parses the input into simple and compound commands.
- The shell performs various expansions (separately) ...
- The shell performs redirection and removes redirection operators and their operands from the parameter list.
- The shell executes a function, built-in, executable file, or script ...
- The shell optionally waits for the command to complete and collects the exit status.
At step 6 a built-in will be executed.
At step 6 eval causes the processed line to be sent back to step 1.
It is the only condition under which the execution sequence goes back.
That is why I say: With eval an input line is parsed twice.
Effects of parsing twice.
The first.
And most important effect to understand. Is that one consequence of the first time a line is subject to the seven shell steps shown above, is quoting. Inside step 4 (expansions), there is also a sequence of steps to perform all expansions, the last of which is Quote Removal:
Quote removal shall always be performed last.
So, always, there is one level of quoting removed.
Second.
As consequence of that first effect, additional/different parts of the line become exposed to the shell parsing and all the other steps.
Example.
Indirection.
That allows to execute indirect expansions:
a=b b=c ; eval echo \$$a ### shall produce "c"
Why?
Because on the first loop, the first $ is quoted.
As such, it is ignored for expansions by the shell.
The next $ with the name a is expanded to produce "b".
Then, one level of quoting is removed, making the first $ unquoted.
End of first loop.
It is then, on the second loop that the string $b is read by the shell.
Then expanded to "c"
And given as an argument to echo.
To "see" what eval will produce on the first loop (to be evaluated again), use echo. Or any command/script/program that clearly shows the arguments:
$ a=b b=c
$ eval echo \$$a;
c
Replace eval by echo to "see" what is happening:
$ echo echo \$$a
echo $b
It is also possible to show all the "parts" of a line with:
$ printf '<%s> ' echo \$$a
<echo> <$b>
Which, in this example, is only one echo and one variable, but remember it to help in evaluating more complex cases.
A correction.
It must be said that: there is a mistake in the code above, can you see it?.
Easy: there are some quotes missing.
How? you may ask. Simple, let's change the variables (not the code):
$ a=b b="hi jk"
$ eval echo \$$a
hi jk
See the missing spaces?
That is because the value inside $b was split by the shell.
If that does not convince you, try this:
$ a=b b="hi * jk"
$ eval echo \$$a ### warning this will expand to the list
### of all files in the present directory.
Why?
Missing quotes. To make it work correctly (add internal "$a"and external \" quotes).
Try this (is perfectly safe):
$ a=b b="hi * jk"
$ eval echo \" \$"$a" \"
hi * jk
About the manual:
There is no man page for it..
No, there is not an independent man page for this.
The search for manual with man -f eval or even apropos eval show no entry.
It is included inside man bash. As is any built-in.
Search for "SHELL BUILTIN COMMANDS" and then for "eval".
An easier way to get help is:
In bash, you could do help eval to see the help for the built-in.
Why is eval called evil?
Because it is binding text to code dynamically.
In other words: it converts the list of its arguments (and/or expansions of such arguments) into an executed line. If for any reason, an argument has been set by an attacker, you will be executing attacker code.
Or even simpler, with eval you are telling whoever defined the value of one or several arguments:
C'mon, sit here and type any command line, I will execute it with my powers.
Is that dangerous? Should be clear for everyone that it is.
The safety rule for eval should be:
Only execute eval on variables to which you have given it's value.
Read more detail here.