¿Cómo almacenar un comando en una variable en Linux?

Me gustaría almacenar un comando para usar en un período posterior en una variable (no el resultado del comando, sino el comando mismo)

Tengo un script simple de la siguiente manera:

command="ls"; echo "Command: $command"; #Output is: Command: ls b=`$command`; echo $b; #Output is: public_html REV test... (command worked successfully) 

Sin embargo, cuando bash algo un poco más complicado, falla. Por ejemplo, si hago

 command="ls | grep -c '^'"; 

El resultado es:

 Command: ls | grep -c '^' ls: cannot access |: No such file or directory ls: cannot access grep: No such file or directory ls: cannot access '^': No such file or directory 

¿Alguna idea de cómo podría almacenar ese comando (con pipes / Multiple Commands) en una variable para su uso posterior?

Use eval:

 x="ls | wc" eval $x y=$(eval $x) echo $y 
 var=$(echo "asdf") echo $var # => asdf 

Usando este método, el comando se evalúa inmediatamente y se almacena su valor de retorno.

 stored_date=$(date) echo $stored_date # => Thu Jan 15 10:57:16 EST 2015 # (wait a few seconds) echo $stored_date # => Thu Jan 15 10:57:16 EST 2015 

Lo mismo con el congulplpe

 stored_date=`date` echo $stored_date # => Thu Jan 15 11:02:19 EST 2015 # (wait a few seconds) echo $stored_date # => Thu Jan 15 11:02:19 EST 2015 

El uso de eval en $(...) no lo evaluará más tarde

 stored_date=$(eval "date") echo $stored_date # => Thu Jan 15 11:05:30 EST 2015 # (wait a few seconds) echo $stored_date # => Thu Jan 15 11:05:30 EST 2015 

Al usar eval, se evalúa cuando eval se utiliza

 stored_date="date" # < storing the command itself echo $(eval $stored_date) # => Thu Jan 15 11:07:05 EST 2015 # (wait a few seconds) echo $(eval $stored_date) # => Thu Jan 15 11:07:16 EST 2015 # ^^ Time changed 

En el ejemplo anterior, si necesita ejecutar un comando con argumentos, colóquelos en la cadena que está almacenando

 stored_date="date -u" # ... 

Para los scripts bash esto rara vez es relevante, pero una última nota. Ten cuidado con eval Evalúa solo las cadenas que controlas, nunca las cadenas provenientes de un usuario que no es de confianza ni las creadas a partir de las entradas de usuarios que no son de confianza.

¡ No uses eval ! Tiene un gran riesgo de introducir la ejecución de código arbitrario.

BashFAQ-50 – Estoy tratando de poner un comando en una variable, pero los casos complejos siempre fallan.

Colóquelo en una matriz y expanda todas las palabras con comillas dobles "${arr[@]}" para que el IFS divida las palabras debido a Word Splitting .

 cmdArgs=() cmdArgs=('date' '+%H:%M:%S') 

y ver el contenido de la matriz dentro. El declare -p permite ver el contenido de la matriz dentro de cada parámetro de comando en índices separados. Si uno de esos argumentos contiene espacios, al cotizar dentro mientras se agrega a la matriz se evitará que se divida debido a Word-Splitting.

 declare -p cmdArgs declare -a cmdArgs='([0]="date" [1]="+%H:%M:%S")' 

y ejecuta los comandos como

 "${cmdArgs[@]}" 23:15:18 

(o) en conjunto usa una función bash para ejecutar el comando,

 cmd() { date '+%H:%M:%S' } 

y llamar a la función como simplemente

 cmd 

POSIX sh no tiene matrices, por lo que lo más cercano que puede venir es crear una lista de elementos en los parámetros posicionales. Aquí hay una forma POSIX sh de ejecutar un progtwig de correo

 # POSIX sh # Usage: sendto subject address [address ...] sendto() { subject=$1 shift first=1 for addr; do if [ "$first" = 1 ]; then set --; first=0; fi set -- "$@" --recipient="$addr" done if [ "$first" = 1 ]; then echo "usage: sendto subject address [address ...]" return 1 fi MailTool --subject="$subject" "$@" } 

No es necesario almacenar comandos en variables incluso si necesita usarlo más adelante. solo ejecútalo como de costumbre. Si almacena en variable, necesitaría algún tipo de statement de eval o invocar algún proceso de shell innecesario para “ejecutar su variable”.