2010-08-12 28 views
7

Intenté ejecutar comandos utilizando tuberías.¿Cómo ejecutar comandos de script desde variables?

básico:

single="ls -l" 
$single 

que funciona como se esperaba

Tubos:

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 

... no es de extrañar

bash < $multi 

$multi: ambiguous redirect 

siguiente intento

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

Sólo

echo $multi > tmp.sh 
bash tmp.sh 

trabajaban.

¿Hay alguna manera de ejecutar comandos más complejos sin crear un script para la ejecución?

+0

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

Respuesta

11

Estás demostrando la diferencia entre el shell y el kernel.

"ls -l" es ejecutable mediante la llamada al sistema execve(). Puede llamar al man execve para obtener más detalles, pero probablemente sean demasiados detalles para usted.

"ls -l | grep e" necesita una interpretación de shell para configurar la tubería. Sin usar un caparazón, el '|' el carácter acaba de pasar a execve() como un argumento para ls. Es por eso que ve los errores "No hay tal archivo o directorio".

Solución:

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

Gracias, ¿alguna idea de por qué "bash -c" imprime la salida en una sola línea? Me gustaría tener el mismo resultado que ingresé manualmente en la línea de comando. – stacker

+0

@stacker No creo que sea cierto.Obtengo el mismo resultado que en la línea de comando. ¿Quizás tu grep solo está devolviendo una sola línea? – bukzor

+0

Esto sucedió porque olvidé incluir la variable entre comillas dobles. – stacker

-3

cuando se quiere ejecutar comandos con tuberías, sólo ejecutarlo. Nunca coloque el comando en una variable e intente ejecutarlo. Simplemente ejecutarlo

ls -l |grep

Si desea capturar la salida, utilice $()

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

+0

Los comandos provienen de un servidor diferente y deben ejecutarse en la máquina de destino. Por lo tanto, no puede ser codificado. – stacker

+0

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

0

Se necesita una heredoc para hacer esto correctamente. En respuesta al POSIX compliant way to see if a function is defined in an sh script, detallé cómo leer un script en una variable, analizarlo programáticamente para obtener información y/o modificarlo según sea necesario, y luego ejecutarlo desde otro script o función de shell. Eso es básicamente lo que estamos tratando de hacer, y la heredoc hace posible, ya que proporciona un descriptor de archivo:

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

que resolvería su caso sencillo ejemplo. Ver mi otra respuesta para más.

-Mike

Cuestiones relacionadas