Tengo file.txt con el comando almacenado en una línea (este comando es válido cuando se ejecuta en la consola) y quiero ejecutarlo en una línea con sh como
cat file.txt | eval
¿Qué está faltando? ¿Algún consejo profesional?
¿Y si tengo un archivo con muchos comandos (uno para cada línea) y quiero ejecutar solo un comando (una línea completa)? mi primera idea es:
head -n5 | tail -n1 | eval
Respuesta1
eval
no lee su cadena de comando desde stdin.
eval "$(cat file.txt)"
# or easier, in ksh/bash/zsh
eval "$(<file.txt)"
# usually you cannot be sure that a command ends at the end of line 5
eval "$(head -n 5 file.txt)"
En lugar de, puede eval
usar estándar .
o bash
// si los comandos están en un archivo de todos modos:zsh
ksh
source
source ./file
(tenga en cuenta que es importante agregar eso ./
. De lo contrario, source
busque file
en $PATH
antes de considerar file
en el directorio actual. Si está en modo POSIX, bash
ni siquiera considerará file
en el directorio actual, incluso si no se encuentra en $PATH
).
Por supuesto, eso no funciona al elegir una parte del archivo. Eso podría hacerse mediante:
head -n 5 file.txt >commands.tmp
source ./commands.tmp
O (con ksh93, zsh, bash):
source <(head -n 5 file.txt)
Respuesta2
entonces... una solución a su pregunta es 100% posible y (en el contexto de make
) importante.
Me encontré con esto con un archivo MAKE y, dada la dificultad de anidar comandos bash en un archivo MAKE que ya utiliza $(...)
para llamar variables, es bueno poder hacer exactamente lo que estás preguntando.
En lugar de usar eval
, simplemente use el comando del sistema awk
o :perl
// command_list.sh:
echo "1"
echo "2"
echo "3"
// command line prompt:
$: cat command_list.sh | awk '{system($0)}'
1
2
3
Y construcción de comandos:
// a readable version--rather than building up an awk miniprogram,
// split into logical blocks:
$: cat inputs.txt | awk '{print "building "$1" command "$2" here "}' | awk '{system($0)}'
Respuesta3
Técnicamente, es imposible evaluar algo dentro de su entorno actual si desea leerlo desde una tubería, ya que cada comando en la tubería se ejecuta como un proceso separado.
Sin embargo, dependiendo de lo que intentes lograr, es posible que eso no importe. En cualquier caso, aquí se ejecuta eval
el contenido de una tubería:
❯ echo echo hi | eval "$(cat -)"
hi
He aquí un ejemplo de la captura. Algo como lo siguiente no se imprimirá 1
:
❯ echo a=1 | eval "$(cat -)"; echo $a
Tendríamos que hacer lo siguiente en su lugar:
❯ echo a=1 | { eval "$(cat -)"; echo $a; }
1
Respuesta4
Si no estás decidido a utilizar eval
, utiliza sh
:
cat file.txt | sh
Sí, se ejecutará en una instancia sh separada, pero ese hecho está autodocumentado.
Y también hay while read
:
cat file.txt | while read cmd; do eval $cmd; done
Para ejecutar el comando en la quinta línea del archivo.txt:
sed -n 5p file.txt | sh
(Me doy cuenta de que esta es una vieja pregunta).