¿Cómo puedo llamar a múltiples comandos como argumentos para una función?


1

Quiero escribir una función "para siempre" en la que pueda ejecutar varios comandos hasta que la elimine manualmente con Ctrl-C. Básicamente, desde la línea de comando zsh, sé que puedo hacer esto, y esto funciona bien:

$ while {} { ls ; sleep 1 }

que repetirá la llamada lsy sleep 1, para siempre.

No puedo entender una sintaxis para convertir algo así en una función. Algo como:

forever() { while {} { "${@}" } }

que luego quiero llamar con algo como:

$ forever ( ls ; sleep 1 )

Probablemente parece tonto cuando while {} {<commands>}y forever {<commands>}apenas es muy diferente. Pero lo que realmente quiero como objetivo final es una función de "sueño para siempre", donde puedo decir algo como

$ forever-sleep 5 ls -l
$ forever-sleep 5 ( ls -l a ; ls -l b )

y dormirá $1segundos después de ejecutar los comandos que le doy, para siempre (hasta que lo mate manualmente con Ctrl-C).

(He intentado un montón de combinaciones y de los agrupamientos (), (()), {}, [], [[]], "", '', y tal, y yo simplemente no puedo encontrar la manera de conseguir tanto la función como la línea de comandos no tienen errores de sintaxis, analizar Errrors, etc. )

Entonces,

  • ¿Hay algo similar a esta idea "para siempre" ya?
  • ¿Es esto posible en una función? (Preferiría una función que pueda incluir en mi en .zshrclugar de tener un script de shell ejecutable separado).

Respuestas:


1

Ya casi estabas allí:

forever-sleep() {
   if [[ ! $1 -gt 0 ]]; then
     print "Usage $0 [time in sec] command -parameter"
     return 2
   fi
   local time=$1
   shift 1
   while true; do
      eval "$@"
      print -- "### finished: $(date) ###############################################"
      sleep $time
   done
}

La sintaxis entonces es forever-sleep [time in sec] command -parameters, como

$ forever-sleep 2 date +%s
1373873888
1373873890
1373873892
1373873894
...

Algunas observaciones:

  • $1 -gt 0implementa una verificación rudimentaria, si el primer parámetro es numéricamente mediante evaluación $1 > 0. Un tiempo de espera negativo no parece sensato.
  • Solía while true; do ... done, pero tu while {} {...}sintaxis también funciona.
  • shift 1se usa para descartar el primer argumento de la función (que se guarda en $time, para que luego la "$@"variable se pueda usar por conveniencia.
  • eval "$@"en contraste con un mero "$@"hace posible hacer algunas cosas más avanzadas como

    forever-sleep 2 'foo=$(date); echo $foo'

    ¡Observe las comillas simples en el último comando!

  • La invocación de impresión proporciona un separador visual, nos guste o no ;)

Hermosa. Gracias. Esto evales lo que me faltaba. (Que sabía sobre shift, pero gracias por la integridad.)
snapshoe
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.