2010-08-12 3 views
7

J'ai essayé d'exécuter des commandes en utilisant des tuyaux.Comment exécuter des commandes de script à partir de variables?

Basic:

single="ls -l" 
$single 

qui fonctionne comme prévu

Pipes:

multi="ls -l | grep e" 
$multi 
ls: |: No such file or directory 
ls: grep: No such file or directory 
ls: e: No such file or directory 

... pas surprenant

bash < $multi 

$multi: ambiguous redirect 

essayer la prochaine

bash $multi 
/bin/ls: /bin/ls: cannot execute binary file 

Seulement

echo $multi > tmp.sh 
bash tmp.sh 

travaillé.

Existe-t-il un moyen d'exécuter des commandes plus complexes sans créer de script à exécuter?

+0

Voir [BashFAQ/050] (http://mywiki.wooledge.org/BashFAQ/050). –

Répondre

11

Vous faites la démonstration de la différence entre le shell et le noyau.

"ls -l" est exécutable par l'appel système execve(). Vous pouvez man execve pour plus de détails, mais c'est probablement trop de détails pour vous. "Ls -l | grep e" nécessite une interprétation de la coquille pour configurer le tuyau. Sans utiliser de shell, le '|' Le caractère est juste passé dans execve() en tant qu'argument à ls. C'est pourquoi vous voyez les erreurs "No such file or directory".

Solution:

cmd="ls -l | grep e" 
bash -c "$cmd" 
+0

Merci, aucune idée pourquoi "bash -c" imprime la sortie sur une seule ligne? Je voudrais avoir la même sortie que celle entrée manuellement sur la ligne de commande. – stacker

+0

@stacker Je ne pense pas que ce soit vrai.Je reçois le même résultat que sur la ligne de commande. Peut-être que votre grep ne renvoie qu'une seule ligne? – bukzor

+0

Cela s'est produit parce que j'ai oublié de placer la variable entre guillemets. – stacker

-3

lorsque vous voulez exécuter des commandes avec des tuyaux, exécutez simplement. Ne placez jamais la commande dans une variable et essayez de l'exécuter. Il suffit d'exécuter ce

ls -l |grep

Si vous voulez capturer la sortie, utilisez $()

var=$(ls -l |grep ..)

+0

Les commandes proviennent d'un serveur différent et doivent être exécutés sur la machine cible. Ainsi, il ne peut pas être codé en dur. – stacker

+0

voir http://mywiki.wooledge.org/BashFAQ/050 – ghostdog74

0

Vous avez besoin d'un heredoc faire correctement. En réponse à POSIX compliant way to see if a function is defined in an sh script, j'ai détaillé comment lire un script dans une variable, l'analyser par programme pour des informations et/ou le modifier si nécessaire, puis l'exécuter à partir d'un autre script ou d'une fonction shell. C'est essentiellement ce que vous essayez de faire, et le heredoc permet, car il fournit un descripteur de fichier:

% multi='ls -l | grep e' 
% sh <<_EOF_ 
> ${multi} 
> _EOF_ 
< desired output > 

Cela résoudrait votre cas de simple exemple. Voir mon autre réponse pour plus.

-Mike