views:

7844

answers:

7

There's a builtin unix command repeat whose first argument is the number of times to repeat a command, where the command (with any arguments) is specified by the remaining arguments to repeat. For example,

% repeat 100 echo "I will not automate this punishment."

will echo the given string 100 times and then stop.

I'd like a similar command, let's call it forever, that works similarly except the first argument is the number of seconds to pause between repeats, and it repeats forever. For example,

% forever 5 echo "This will get echoed every 5 seconds forever and ever."

I thought I'd ask if such a thing exists before I write it. I know it's like a 2-line perl or python script but maybe there's a more standard way to do this. If not, feel free to post a solution in your favorite scripting language, rosetta stone style.

PS: Maybe a better way to do this would be to generalize repeat to take both the number of times to repeat (with -1 meaning infinity) and the number of seconds to sleep between repeats. The above examples would then become:

% repeat 100 0 echo "I will not automate this punishment."
% repeat -1 5 echo "This will get echoed every 5 seconds forever."
+9  A: 

Bash

while + sleep

while true
do 
    echo "Hi"
    sleep 1
done
pope
Cool, thanks; which shell is that? But note that I'm looking for something you execute as a single command-line command.
dreeves
I believe it works as written in a generic Bourne shell, as well.
dmckee
+1  A: 

Perl

#!/usr/bin/env perl
# First argument is number of seconds to sleep between repeats, remaining
# arguments give the command to repeat forever.

$sleep = shift;
$cmd = join(' ', @ARGV);

while(1) {
  system($cmd);
  sleep($sleep); 
}
dreeves
+2  A: 

I like the scripts, but an alternate approach would be to use cron...at least for n = m*60

::blushes:: Hangs head in shame. Thanks Jonathan.

dmckee
cron doesn't work at second granularities - minutes are as small as it works with.
Jonathan Leffler
Aye, there's that...
dmckee
+32  A: 

try the 'watch' command.

Usage: watch [-dhntv] [--differences[=cumulative]] [--help] [--interval=] [--no-title] [--version]

watch -n1 command

will run the command every second, forever

OP has asked for link to OS X version of watch: http://www.macports.org/

gbrandt
Aha, thanks! I don't have that on my system (Mac OS X) -- do you have a link?
dreeves
you can use MacPorts to install it. sudo port install watch
pope
fink has a package...
dmckee
+3  A: 

In bash:

bash -c 'while [ 0 ]; do echo "I will not automate this punishment in absurdum."; done'

(Echo could be replaced by any command...

Or in Perl:

perl -e 'for (;1;) {print "I will not automate this punishment in absurdum.\n"}'

Where print "I will not automate this punishment in absurdum.\n" could be replaced with "any" command surrounded with backticks (`).

And for a pause add a sleep statement inside the for loop.

bash -c 'while [ 0 ]; do echo "I will not automate this punishment in absurdum."; sleep 1; done'

and

perl -e 'for (;1;) {print "I will not automate this punishment in absurdum.\n"; sleep 1}'
Tooony
+1  A: 

Care to try this out (Bash)?

forever ()   {
    TIMES=shift;
    SLEEP=shift;
    if [ "$TIMES" = "-1" ]; then  
        while true;
        do 
            $@
            sleep $SLEEP
        done
    else
        repeat "$TIMES" $@ 
    fi; }
Gregg Lind
I'm not to hot at shell, so improvements welcome. And I don't seem to have a "repeat" command in my distro.
Gregg Lind
+1  A: 

As mentioned by gbrandt, if the 'watch' command is available, definitely use it. Some Unix systems, however, don't have it installed by default (at least they don't where I work).

Here's another solution with slightly different syntax and output (works in BASH and SH):

while [ 1 ] ; do
    <cmd>
    sleep <x>
    echo ">>>>>>>>>>>>>" `date` ">>>>>>>>>>>>>>"
done

Edit: I removed some "." in the last echo statement...holdover from my Perl days ;)

bedwyr