Unix Power Tools
by Mike Loukides
eval: When You Need Another Chance
Most of the time, the shell evaluates the command line "in the right order." But what about when it doesn't? Here's a situation that the shell can't handle. It's admittedly contrived, but not too different from what you might find in a shell program:
When we use the variable $b, we'd like to get the variable $a, read it, and use its value. But that doesn't happen. Variable substitution happens once, and it isn't recursive. The value of $b is $a, and that's it. You don't go any further.
But there's a loophole. The eval command says, in essence, "Give me another chance. Re-evaluate this line and execute it." Here's what happens if we stick eval before the echo:
The shell converts $b into $a; then eval runs through the command-line evaluation process again, converting echo $a into echo foo - which is what we wanted in the first place!
Here's a more realistic example; you see code like this fairly often in Bourne shell scripts:
Do you see what's happening? We're constructing a command that will look something like:
But the entire command is "hidden" in shell variables, including the I/O redirectors and various options. If the eval isn't there, this command will blow up in all sorts of bizarre ways. You'll see messages like | not found, because variable expansion occurs after output redirection. The "nested" variables (like $ofile, which is used inside of $output) won't be expanded either, so you'll also see $ofile not found. Putting an eval in front of the command forces the shell to process the line again, guaranteeing that the variables will be expanded properly and that I/O redirection will take place.
eval is incredibly useful if you have shell variables that include other shell variables, shell variables that include aliases, shell variables that include I/O redirectors, or all sorts of perversities. It's commonly used within shell scripts to "evaluate" commands that are built during execution.