1

I want to write a "forever" function that I can run multiple commands until I manually kill it with Ctrl-C. Basically, from the zsh command line, I know I can do this, and this works fine:

$ while {} { ls ; sleep 1 }

which will repeated call ls and sleep 1, forever.

I can't figure out a syntax to turn something like that into a function. Something like:

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

which I want to then then call with something like:

$ forever ( ls ; sleep 1 )

It probably seems silly when while {} {<commands>} and forever {<commands>} is hardly very different. But what I really want as my end goal is a "forever-sleep" function, where I can say something like

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

and it will sleep $1 seconds after executing the command(s) I give it, forever (until I manually kill it with Ctrl-C).

(I've tried lots of combinations and nestings of (),(()),{},[],[[]],"",'', and such, and I just can't figure out how to get both the function and the command line not to have syntax errors, parse errrors, etc.)

So,

  • Is there something similar to this "forever" idea already?
  • Is this possible in a function? (I would prefer a function I can put in my .zshrc rather than having a separate executable shell script.)

1 Answer 1

1

You were almost there:

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
}

The syntax then is forever-sleep [time in sec] command -parameters, like

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

A few remarks:

  • $1 -gt 0 implements a rudimentary check, if the first parameter is numerically by evaluating $1 > 0. A negative waiting time seems not sensible.
  • I used while true; do ... done, but your while {} {...} syntax works, too.
  • shift 1 is used to discard the first argument to the function (which is saved in $time, so that later the "$@" variable can be used for convenience.
  • eval "$@" in contrast to a mere "$@" makes it possible to do some more advanced stuff like

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

    Please notice the single quotes in the latter command!

  • The print invocation gives a visual separator -- like it or not ;)
1
  • Beautiful. Thank you. The eval is what I was missing. (I knew about shift, but thanks for the completeness.)
    – snapshoe
    Jul 15, 2013 at 15:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .