Quelle est la bonne façon d'appeler une commande stockée dans variable?
Y at-il des différences entre 1 et 2?
#!/bin/sh
cmd="ls -la $APPROOTDIR | grep exception"
#1
$cmd
#2
eval "$cmd"
Les shells Unix effectuent une série de transformations sur chaque ligne d’entrée avant de les exécuter. Pour la plupart des shells, cela ressemble à ceci (tiré de la page de manuel bash
):
En utilisant $cmd
le récupère directement par votre commande lors de la phase de développement des paramètres, puis il subit toutes les transformations suivantes.
En utilisant eval "$cmd"
ne fait rien jusqu’à la phase de suppression des devis, où $cmd
est retourné tel quel et passé comme paramètre à eval
, dont la fonction est de réexécuter toute la chaîne avant de l'exécuter.
En gros, ils sont identiques dans la plupart des cas et diffèrent lorsque votre commande utilise les étapes de transformation pour développer les paramètres. Par exemple, en utilisant l’accolade:
$ cmd="echo foo{bar,baz}"
$ $cmd
foo{bar,baz}
$ eval "$cmd"
foobar foobaz
Si vous ne faites que eval $cmd
quand on fait cmd="ls -l"
(de manière interactive et dans un script), nous obtenons le résultat souhaité. Dans votre cas, vous avez un tube avec un grep sans motif, donc la partie grep échouera avec un message d'erreur. Juste $cmd
générera un message "commande introuvable" (ou un message similaire). Essayez donc d'utiliser eval et d'utiliser une commande terminée, pas une qui génère un message d'erreur.
$cmd
_ remplacerait simplement la variable par sa valeur à exécuter en ligne de commande. eval "$cmd"
effectue une extension de variable et une substitution de commande avant d'exécuter la valeur résultante en ligne de commande
La deuxième méthode est utile lorsque vous souhaitez exécuter des commandes qui ne sont pas flexibles, par exemple.for i in {$a..$b}
La boucle de formatage ne fonctionnera pas car elle n'autorise pas les variables.
Dans ce cas, une pipe à bash ou à eval est une solution de contournement.
testé sur Mac OSX 10.6.8, Bash 3.2.48