¿Cómo ejecutar el comando almacenado en una variable?

¿Cuál es la forma correcta de llamar a algún comando almacenado en una variable?
¿Hay alguna diferencia entre 1 y 2?

#!/bin/sh cmd="ls -la $APPROOTDIR | grep exception" #1 $cmd #2 eval "$cmd" 

Las shells de Unix operan una serie de transformaciones en cada línea de entrada antes de ejecutarlas. Para la mayoría de las conchas se ve algo como esto (tomado de la página de manual de bash ):

  • división inicial de palabras
  • expansión de la abrazadera
  • expansión de tilde
  • ampliación de parámetros, variables y aritmética
  • sustitución de comando
  • división de palabras secundarias
  • expansión de ruta (también conocida como globbing)
  • eliminación de cotizaciones

El uso de $cmd lo reemplaza directamente por su comando durante la fase de expansión del parámetro, y luego se somete a todas las siguientes transformaciones.

El uso de eval "$cmd" no hace nada hasta la fase de eliminación de cotizaciones, donde $cmd se devuelve tal como está, y se pasa como un parámetro a eval , cuya función es ejecutar toda la cadena nuevamente antes de ejecutar.

Básicamente, son los mismos en la mayoría de los casos y difieren cuando su comando utiliza los pasos de transformación hasta la expansión de parámetros. Por ejemplo, usando la expansión de llaves:

 $ cmd="echo foo{bar,baz}" $ $cmd foo{bar,baz} $ eval "$cmd" foobar foobaz 

Si solo hace eval $cmd cuando hacemos cmd="ls -l" (interactivamente y en un script) obtenemos el resultado deseado. En su caso, tiene una tubería con un grep sin patrón, por lo que la parte grep fallará con un mensaje de error. Solo $cmd generará un mensaje de “comando no encontrado” (o algo así). Intente utilizar eval y use un comando finalizado, no uno que genere un mensaje de error.

Creo que pones `símbolos alrededor de tu variable (la que tiene ~ si se presiona Shift)