Using the eval command in Linux to run variables as commands

The eval command allows you to run the contents of variables as commands and can be very useful, especially in scripts.

There are probably a lot of Linux users who have never encountered the eval command. In fact, it’s not really a "command", but a bash built-in that’s meant to process the value of a variable as a command. For example, if you set up a variable that includes the command to display the current time in Sydney, Australia, it would probably look like this:

$ dt="TZ='Australia/Sydney' date"

You could then run it like this:

$ eval $dt

Thu Jul  7 06:32:14 AM AEST 2022

Doing that can save you the trouble of memorizing the date command syntax and specifying a time zone, but let’s look a little more closely at eval to see what else it can do for you.

The bash man page will tell you a little about the eval command, though you would have to scroll down nearly 5,000 lines to find it. There are, after all, no man pages for built-ins. Here's what it would tell you:

    The args are read and concatenated together into a  single  com-

    mand.   This command is then read and executed by the shell, and

    its exit status is returned as the value of eval.  If there  are

    no args, or only null arguments, eval returns 0.

Of course, for anything you do by typing commands in the terminal window, eval isn't likely to save you much time or effort. You could, after all, create an alias to do the same work for you. Here’s how that would look:

$ alias dt="TZ='Australia/Sydney' date"

$ dt

Thu Jul  7 06:37:31 AM AEST 2022

Save that alias in your .bashrc file, and you’ll have an easy time checking what time it is in Sydney whenever you feel the urge.

When you're building a complex command in pieces, however—especially in scripts that need to collect the necessary data when they are run—using eval to run the command can make running the command a lot easier.

As an example, while working on a recent script, I needed to find words that were five letters long, had specific letters in known positions and other specific letters in uncertain positions. I also knew that a number of letters were not included in the words that I needed to find. Step-by-step, the script built a long string of grep commands to look through the words file to find only the words that fit my specifications. Here’s an example of what such a command might look like with all of its grep (match) and its grep -v (ignore) commands and the match that it found:

$ grep ^ch..t$ /usr/share/dict/words | eval grep -v 'q' | grep -v 'w' | grep -v 'r' | grep -v 'y' | grep -v 'u' | grep -v 'i' | grep -v 'o' | grep -v 'p' | grep -v 's' | grep -v 'd' | grep -v 'f' | grep -v 'g' | grep -v 'j' | grep -v 'k' | grep -v 'l' | grep -v 'z' | grep -v 'x' | grep -v 'v' | grep -v 'b' | grep -v 'n' | grep -v 'm' | grep a | grep e | grep -v ..a.. | grep -v ...e.

cheat

In fact, if you run that command against your words file, you should get the same response. If you turn it into a variable as shown below, it will work the same.

$ cmd="grep ^ch..t$ /usr/share/dict/words | grep -v 'q' | grep -v 'w' | grep -v 'r' | grep -v 'y' | grep -v 'u' | grep -v 'i' | grep -v 'o' | grep -v 'p' | grep -v 's' | grep -v 'd' | grep -v 'f' | grep -v 'g' | grep -v 'j' | grep -v 'k' | grep -v 'l' | grep -v 'z' | grep -v 'x' | grep -v 'v' | grep -v 'b' | grep -v 'n' | grep -v 'm' | grep a | grep e | grep -v ..a.. | grep -v ...e."

$ eval $cmd

cheat

My script uses eval to run the $cmd variable as a command and passes the output to the column command which makes the output more useful when there are dozens or hundreds of matching words. The result in the example shown was the single word “cheat” pulled from the nearly half a million lines in the words file. All I needed to do was answer a few questions about what I knew and didn’t know.

eval $cmd | column

Wrap-Up

The eval command can be used to run simple or very complex commands that are saved as variables. It evaluates the commands and arguments in the variable and then executes them. It’s most useful when you are constructing long and complicated commands – especially in scripts when the details depend on data that changes or responses provided when the scripts are run.

un.

Join the Network World communities on Facebook and LinkedIn to comment on topics that are top of mind.
Related:

Copyright © 2022 IDG Communications, Inc.