How to execute a command stored in a variable?

What is the correct way to invoke some command stored in a variable?
Are there any differences between 1 and 2?

#!/bin/sh cmd="ls -la $APPROOTDIR | grep exception" #1 $cmd #2 eval "$cmd" 
+72
unix shell parameter-expansion
Jan 12 '11 at 12:13
source share
4 answers

Unix shells perform a series of conversions on each line of input before executing them. For most shells, it looks something like this (taken from the bash manpage):

  • splitting of the initial word
  • bracket extension
  • tilde expansion
  • parameter, variable and arithmetic expansion
  • command substitution
  • word splitting
  • extension of the path (aka globe)
  • delete quote

Using $cmd directly replaces it with your command during the parameter expansion phase, and then undergoes all of the following conversions.

Using eval "$cmd" does nothing until the delete phase of the quote, where $cmd returned as is, and passed as a parameter to eval , whose function is to start the whole chain again before executing.

Basically, they are mostly the same and different when your team uses the conversion steps before expanding the parameters. For example, using a parenthesis extension:

 $ cmd="echo foo{bar,baz}" $ $cmd foo{bar,baz} $ eval "$cmd" foobar foobaz 
+85
Jan 12 '11 at 12:29
source share

If you just do eval $cmd when we do cmd="ls -l" (interactively and in script), we get the desired result. In your case, you have a pipe with grep without a template, so the grep command will end with an error message. Just $cmd will generate the message "command not found" (or some such). So try using eval and use ready-made commands, not the ones that generate the error message.

+5
Jan 12 '11 at 12:25
source share

$cmd will simply replace the variable with the value that will be executed on the command line. eval "$cmd" performs variable expansion and command substitution before executing the resulting value on the command line

The 2nd method is useful when you want to execute commands that are not flexible, for example.
for in {$a..$b}
The formatting loop will not work because it does not allow variables.
In this case, the workaround is bash or eval.

Tested on Mac OSX 10.6.8, Bash 3.2.48

0
Jun 18 '19 at 17:10
source share

I think you should put

 ' 

(backtick) characters around your variable.

-four
Jan 12 '11 at 12:15
source share



All Articles