Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

There's a built-in 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."
share|improve this question

migrated from stackoverflow.com Apr 5 '11 at 9:44

This question came from our site for professional and enthusiast programmers.

Why not: repeat [-t time] [-n number] command [args...]? – Jonathan Leffler Feb 17 '09 at 0:22
Cool. Unfortunately both on my Ubuntu and my AIX repeat is command not found. Can you do a type repeat and let me know where's coming from? – Davide Nov 22 '09 at 23:47
I'm also on Ubuntu and don't have repeat installed. Any information on how to install this would be helpful. – Rory Dec 21 '09 at 13:02
repeat is a builtin command in csh and tcsh. – Keith Thompson Jan 12 '12 at 9:25
@KeithThompson, csh, tcsh and zsh. Though it's more a keyword than a builtin – Stéphane Chazelas Oct 21 '12 at 9:54

23 Answers 23

Try the watch command.

Usage: watch [-dhntv] [--differences[=cumulative]] [--help] [--interval=<n>] 
             [--no-title] [--version] <command>`

So that:

watch -n1  command

will run the command every second, forever.

On Mac OS X, you can get watch from Mac Ports, or you can get it via Homebrew:

brew install watch
share|improve this answer
Aha, thanks! I don't have that on my system (Mac OS X) -- do you have a link? – dreeves Feb 17 '09 at 0:24
you can use MacPorts to install it. sudo port install watch – pope Feb 17 '09 at 0:27
Also available in homebrew (brew install watch). – Lyle May 12 '11 at 21:45
+1 For a new powerful tool. I used to while true; do X; sleep Y; done - This is way better. – Adam Matan May 16 '11 at 11:14
It is called cmdwatch on FreeBSD (from the ports: sysutils/cmdwatch). – Ouki Mar 25 '14 at 21:29


while + sleep:

while true
    echo "Hi"
    sleep 1

Here's the same thing as a shorthand one-liner (From the comments below):

while sleep 1; do echo "Hi"; done

Uses ; to separate commands and uses sleep 1 for the while test since it always returns true. You can put more commands in the loop - just separate them with ;

share|improve this answer
Cool, thanks; which shell is that? But note that I'm looking for something you execute as a single command-line command. – dreeves Feb 17 '09 at 0:19
I believe it works as written in a generic Bourne shell, as well. – dmckee Feb 17 '09 at 0:24
@dreeves, using ";" as separator, commands can be execeted in a single line. Look at Toony's answer as a example – bbaja42 Jan 12 '12 at 9:00
sleep 1 always returns true so you can use it as the while condition. Not the most readable thing in the world but absolutely legit: while sleep 1; do echo "Hi"; done – David Costa Jan 12 '12 at 10:46
@IncnisMrsi I didn't think of it, it actually returns zero only when the time has passed and non-zero when it is terminated by a signal. Thanks for pointing it out – David Costa Sep 13 '15 at 9:58

One problem that all the answers posted so far have is that the time the command is executed can drift. For example, if you do a sleep 10 between commands, and the command takes 2 seconds to run, then it's going to run every 12 seconds; if it takes a variable amount of time to run, then over the long term the time when it runs can be unpredictable.

This might be just what you want; if so, use one of the other solutions, or use this one but simplify the sleep call.

For one-minute resolution, cron jobs will run at the specified time, regardless of how long each command takes. (In fact a new cron job will launch even if the previous one is still running.)

Here's a simple Perl script that sleeps until the next interval, so for example with an interval of 10 seconds the command might run at 12:34:00, 12:34:10, 12:34:20, etc., even if the command itself takes several seconds. If the command runs more than interval seconds, the next interval will be skipped (unlike cron). The interval is computed relative to the epoch, so an interval of 86400 seconds (1 day) will run at midnight UTC.


use strict;
use warnings;

if (scalar @ARGV < 2) {
    die "Usage: $0 seconds command [args...]\n";

$| = 1;  # Ensure output appears

my($interval, @command) = @ARGV;

# print ">>> interval=$interval command=(@command)\n";

while (1) {
    print "sleep ", $interval - time % $interval, "\n";
    sleep $interval - time % $interval;
    system @command; # TODO: Handle errors (how?)
share|improve this answer
See also this other question – Stéphane Chazelas Oct 21 '12 at 9:52

This is just a shorter version of other while+sleep answers, if you are running this kind of tasks often as your daily routine, using this saves you from unnecessary key presses, and if your command line starts to get longer understanding this one is a bit easier. But this one starts with sleeping first.

This is generally useful if you need to follow something has one-line output like machine load:

while sleep 1; do uptime; done
share|improve this answer
Yes. This should be documented next to UUOC. – Johan Mar 15 '13 at 9:05
And if you want it to operate like "watch" you can do while clear; do date; command;sleep 5; done – Johan Mar 15 '13 at 9:12

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'


perl -e 'for (;1;) {print "I will not automate this punishment in absurdum.\n"; sleep 1}'
share|improve this answer
while [ 0 ] is a bad way to write it. It means 0 is a string with length > 0. while [ 1 ] or while [ jeff ] would do the same thing. Better to write while true. – Mikel Apr 5 '11 at 10:17
@Mikel: Or while : – Keith Thompson Jan 12 '12 at 9:27

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.

share|improve this answer
cron doesn't work at second granularities - minutes are as small as it works with. – Jonathan Leffler Feb 17 '09 at 0:21
Aye, there's that... – dmckee Feb 17 '09 at 0:22
With the single-line shell answers, the disadvantage is if they die, it just stops forever. With cron, it starts a new one each time. – kurtm Oct 17 '13 at 17:32

I think all the answer here so far are either too convoluted, or instead answer a different question:

  • "How to run a program repeatedly so that there are X seconds delay between when the program finished, and the next starts".

The real question was:

  • "How to run a program every X seconds"

These are two very different things when the command takes time to finish.

Take for instance the script foo.sh (pretend this is a program that takes a few seconds to complete).

# foo.sh
echo `date +"%H:%M:%S"` >> output.txt;
sleep 2.5;
# ---

You wish to run this every second, and most would suggest watch -n1 ./foo.sh, or while sleep 1; do ./foo.sh; done. However, this gives the output:


Which is not exactly being run every second. Even with the -p flag, as the man watch page suggests might solve this, the result is the same.

An easy way to accomplish the desired task, which some touch on, is to run the command in the background. In other words:

while sleep 1; do (./foo.sh &) ; done

And that is all there is to it.

You could run it every 500 ms with sleep 0.5, or what have you.

share|improve this answer
Those who voted on different answers, do not understand the elegance of your answer... – Serge Stroobandt Jun 26 '15 at 22:58
This is good unless your program has side effects. If the program takes longer than the interval, the side effects can interfere (like overwriting a file). If the program waits for something else, and that something else is taking forever, then you're starting more and more background jobs indefinitely. Use with caution. – John Moeller Jul 16 '15 at 20:36

Recent bash >= 4.2 under recent Linux kernel, based answer.

In order to limit execution time, there is no forks! Only built-in are used.

Under recent linux kernels, there is a procfile /proc/timer_list containing time information in nanoseconds.

Depending on granularity and duration of submited command...

If you wanna run a command exactly once by second, your command have to end in less than a second! And from there, you have to sleep only the rest of current seconds...

If delay is more important and your command don't require significant time, you could:

command=(echo 'Hello world.')
while :;do
    printf -v now "%(%s)T" -1
    read -t $(( delay-(now%delay) )) foo

But if you're goal is to obtain finer granularity, you have to

Use nanoseconds information to wait until begin of a second...

For this, I wrote a little bash function:

# bash source file for nano wait-until-next-second

mapfile  </proc/timer_list _timer_list
for ((_i=0;_i<${#_timer_list[@]};_i++));do
    [[ ${_timer_list[_i]} =~ ^now ]] && TIMER_LIST_READ=$_c
    [[ ${_timer_list[_i]} =~ offset:.*[1-9] ]] && \
        TIMER_LIST_OFFSET=${_timer_list[_i]//[a-z.: ]} && \
unset _i _timer_list _c
waitNextSecondHires() {
    local nsnow nsslp
    read -N$TIMER_LIST_READ nsnow </proc/timer_list
    nsnow=${nsnow%% nsecs*}
    nsnow=$((${nsnow##* }+TIMER_LIST_OFFSET))
    read -t .${nsslp:1} foo

After sourcing them, you could:

command=(echo 'Hello world.')
while :;do

run ${command[@]} directly on command line, than compare to

command=(eval "echo 'Hello world.';sleep .3")
while :;do

this must give exactly same result.

share|improve this answer
read -t is a built-in, while sleep is not. This could have border effect (ie hitting [key:return] interrupt quietly the sleep), but this could be treated by testing $foo – F. Hauri Jan 29 '14 at 17:34
Very impressive answer – gena2x Jun 4 '14 at 13:37

Care to try this out (Bash)?

forever ()   {
    if [ "$TIMES" = "-1" ]; then  
        while true;
            sleep $SLEEP
        repeat "$TIMES" $@ 
    fi; }
share|improve this answer
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 Feb 17 '09 at 0:40
repeat is specific to csh and tcsh. – Keith Thompson Jan 12 '12 at 9:42


#!/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) {
share|improve this answer

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
    sleep <x>
    echo ">>>>>>>>>>>>>" `date` ">>>>>>>>>>>>>>"

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

share|improve this answer
while [ 1 ] only works because 1 is treated as a string, just like while [ -n 1 ]. while [ 0 ] or while [ jeff ] would do the same thing. while true makes much more sense. – Mikel Apr 5 '11 at 10:19

If your intention is not to display a message to your screen, and if you could afford to repeat the job in terms of minutes, crontab, perhaps, would be your best tool. For example, if you wish to execute your command every minute, you would write something like this in your crontab file:

* * * * * my_precious_command

Please check out the tutorial for further example. Also, you can set the timings easily using Crontab Code Generator.

share|improve this answer

You could source this recursive function:

ininterval () {
    sleep $delay
    ininterval $delay $*

or add an:

ininterval $*

and call the script.

share|improve this answer

... I wonder how much complicated solutions can be created when solving this problem.

It can be so easy...

open /etc/crontab 

put there 1 next line to the end of file like:

*/NumberOfSeconds * * * * user /path/to/file.sh

If you want to run something every 1 second, just put there:

*/60 * * * * root /path/to/file.sh 

where that file.sh could be chmod 750 /path/to/file.sh

and inside of that file.sh should be:

#What does it do
#What is it runned by

your code or commands

and thats all!


share|improve this answer
This is not correct. */60 is going to run every 60 minutes, and */5, for example, every 5 minutes. – mika Oct 2 '13 at 17:47

Bash and some of its kindred shells have the convenient (( ... )) notation wherein arithmetic expressions can be evaluated.

So as an answer to your third challenge, where both the repeat count and delay between each repeat should be configurable, here's one way to do it:


while (( i++ < repet )); do
  echo Repetition $i
  sleep $delay

This answer also suffers from the timing drift covered in Keith's answer.

share|improve this answer

You could run a script from init (adding a line to /etc/inittab). This script must run your command, sleep for the time you want to wait until run the script again, and exit it. Init will start your script again after exit.

share|improve this answer

What if we had both ?

Here's the idea : with only "interval", it repeats forever. With "interval" and "times", it repeats this number of times, separated by "interval".

The usage :

$ loop [interval [times]] command

So, the algorithm will be :

  • List item
  • if $1 contains only digits, it is the interval (default 2)
  • if $2 contains only digits, it is the number of times (default infinite)
  • while loop with these parameters
    • sleep "interval"
    • if a number of times has been given, decrement a var until it is reached

Therefore :

loop() {
    local i=2 t=1 cond

    [ -z ${1//[0-9]/} ] && i=$1 && shift
    [ -z ${1//[0-9]/} ] && t=$1 && shift && cond=1
    while [ $t -gt 0 ]; do 
        sleep $i
        [ $cond ] && : $[--t]
share|improve this answer
Note: it does not work with floats, despite sleep does accept them. – Baronsed Nov 11 '13 at 22:37

Easy way to repeat a job from crontab with an interval less than one minute (20 seconds example) :

crontab: * * * * * script.sh


>>type your commands here.

sleep 20
>>retype your commands here.

sleep 20
>>retype your commands here.
share|improve this answer

I wound up up creating a variant on swalog's answer. With his you had to wait X seconds for the first iteration, I'm also running my in the foreground so..

./foo.sh;while sleep 1; do (./foo.sh) ; done
share|improve this answer

This solution works in MacOSX 10.7. It works wonderfully.

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

In my case

bash -c 'while [ 0 ]; do ls; done'


bash -c 'while [ 0 ]; do mv "Desktop/* Documents/Cleanup"; done'

to clean up my desktop constantly.

share|improve this answer
Did you mean to have a sleep command there? – Keith Thompson Jan 12 '12 at 9:41
while [ 0 ] is an odd way to write an infinite loop; it works because the test command (also known as [) treats a non-empty string as true. while : ; do ... ; done is more idiomatic, or if you prefer you can use while true ; do ... ; done. – Keith Thompson Jan 17 '12 at 8:11

To repeatedly run a command in a console window I usually run something like this:

while true; do (run command here); done

This works for multiple commands as well, for example, to display a continually updating clock in a console window:

while true; do clear; date; sleep 1; done

share|improve this answer
Why the downvote? You can see this is a working solution by copy and pasting the example into a terminal window. – Thomas Bratt Jan 27 '13 at 14:20
I think you got down voted because it is a little bit dangerous and consumes the CPU. – ojblass Jul 6 '13 at 20:22
#! /bin/sh

# Run all programs in a directory in parallel
# Usage: run-parallel directory delay
# Copyright 2013 by Marc Perkel
# docs at http://wiki.junkemailfilter.com/index.php/How_to_run_a_Linux_script_every_few_seconds_under_cron"
# Free to use with attribution

if [ $# -eq 0 ]
   echo "run-parallel by Marc Perkel"
   echo "This program is used to run all programs in a directory in parallel" 
   echo "or to rerun them every X seconds for one minute."
   echo "Think of this program as cron with seconds resolution."
   echo "Usage: run-parallel [directory] [delay]"
   echo "Examples:"
   echo "   run-parallel /etc/cron.20sec 20"
   echo "   run-parallel 20"
   echo "   # Runs all executable files in /etc/cron.20sec every 20 seconds or 3 times a minute."
   echo "If delay parameter is missing it runs everything once and exits."
   echo "If only delay is passed then the directory /etc/cron.[delay]sec is assumed."
   echo 'if "cronsec" is passed then it runs all of these delays 2 3 4 5 6 10 12 15 20 30'
   echo "resulting in 30 20 15 12 10 6 5 4 3 2 executions per minute." 

# If "cronsec" is passed as a parameter then run all the delays in parallel

if [ $1 = cronsec ]
   $0 2 &
   $0 3 &
   $0 4 &
   $0 5 &
   $0 6 &
   $0 10 &
   $0 12 &
   $0 15 &
   $0 20 &
   $0 30 &

# Set the directory to first prameter and delay to second parameter


# If only parameter is 2,3,4,5,6,10,12,15,20,30 then automatically calculate 
# the standard directory name /etc/cron.[delay]sec

if [[ "$1" =~ ^(2|3|4|5|6|10|12|15|20|30)$ ]]

# Exit if directory doesn't exist or has no files

if [ ! "$(ls -A $dir/)" ]

# Sleep if both $delay and $counter are set

if [ ! -z $delay ] && [ ! -z $counter ]
   sleep $delay

# Set counter to 0 if not set

if [ -z $counter ]

# Run all the programs in the directory in parallel
# Use of timeout ensures that the processes are killed if they run too long

for program in $dir/* ; do
   if [ -x $program ] 
      if [ "0$delay" -gt 1 ] 
         timeout $delay $program &> /dev/null &
         $program &> /dev/null &

# If delay not set then we're done

if [ -z $delay ]

# Add delay to counter

counter=$(( $counter + $delay ))

# If minute is not up - call self recursively

if [ $counter -lt 60 ]
   . $0 $dir $delay &

# Otherwise we're done
share|improve this answer

Quick, dirty and probably dangerous to boot, but if you're adventurous and know what you're doing, put this into repeat.sh and chmod 755 it,

while true
    eval $1 
    sleep $2 

Invoke it with ./repeat.sh <command> <interval>

My spidey sense says this is probably an evil way of doing this, is my spidey sense right?

share|improve this answer
Eval!? What for? sleep $1; shift; "$@" or similar would be much better. – Mikel Apr 20 '12 at 2:01
Dunno why this is -2. eval may be overkill... except when you need it. Eval lets you get things like redirection onto the command line. – Johan Mar 15 '13 at 9:07

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.