78

I'm trying to figure out a simple way to keep re-executing a command whenever it finishes, for any reason (error or otherwise).

What would be the best way to approach this?

EDIT: I wasn't clear enough before. I need the next execution to wait until the previous one finishes.

EDIT 2: Almost all answers work great. I mistakenly thought most answers would either fork the process or re-execute it just once, neither of which is wanted.

2
  • 1
    You still aren't clear. It'd help if you mentioned what program you're executing.
    – Daniel Beck
    Nov 27, 2011 at 13:38
  • 2
    -1 This question does not show any research effort, as the user commented that answers didn't work instead of actually trying to do what they suggest.
    – Daniel Beck
    Nov 30, 2011 at 20:04

7 Answers 7

50

This creates an infinite loop, executing command over and over again.

while :
do
    command
done
5
  • Please see the edit to the original question. I need to keep re-executing it over and over again, not just once.
    – user107012
    Nov 27, 2011 at 13:31
  • 8
    @calcifer This answer works quite well. There's something unusual about your program that none of the four users answering so far anticipated and you failed to mention it.
    – Daniel Beck
    Nov 27, 2011 at 13:39
  • @calcifer this is an infinite loop. it keeps repeating until the end of time (well, until the script is terminated anyways) Nov 27, 2011 at 19:44
  • 1
    My bad, I thought this (and all the other answers) will either fork the process or re-execute it just once, neither of which is wanted. So yes, this answer works. Thanks.
    – user107012
    Nov 27, 2011 at 19:48
  • 1
    one line version: while true; do echo 'Hit CTRL+C'; sleep 1; done, thanks to cyberciti.biz/faq/bash-infinite-loop
    – jk2K
    Nov 11, 2018 at 16:18
118

The watch command will repeat a command forever with an interval specified:

watch -n0 <command>

Setting -n to zero effectively puts the interval at nothing (I think it is really .1 seconds).

watch also has the added benefits of aligning the output so visual changes can be seen easily, and has a switch to highlight changes from the last run.

Reference: the watch man page:

watch runs command repeatedly, displaying its output (the first screenfull). This allows you to watch the program output change over time. By default, the program is run every 2 seconds; use -n or --interval to specify a different interval.

watch will run until interrupted.

9
  • Please see the edit to the original question.
    – user107012
    Nov 27, 2011 at 13:30
  • 6
    All of the answers so far do this, including this one. Linux won't fork unless you specifically ask it to.
    – Paul
    Nov 27, 2011 at 13:34
  • 1
    I can't see any output using this method.
    – khatchad
    Mar 8, 2016 at 1:37
  • @RaffiKhatchadourian Are you saying if you do watch ls in a directory that contains files, you don't get anything?
    – Paul
    Mar 8, 2016 at 1:40
  • actually I was doing it with offlineimap.
    – khatchad
    Mar 8, 2016 at 3:08
20

A simple solution would be:

yourcommand; !#

; separates commands, allowing for multiple commands in one line (Bash: Lists)

!# tells bash to "repeat everything I have written so far in this line" (Bash: Event-Designators)

3
  • 1
    Sorry, I wasn't clear enough. I need to keep re-executing it over and over again, not just once.
    – user107012
    Nov 27, 2011 at 13:27
  • Thanks for this, I was looking for it, especially since yourcommand; !! does not actually work with commands on the same line, however, !# seems to do. Cheers!
    – sdaau
    Jan 25, 2015 at 21:11
  • 1
    ; !# didn't work on ZSH, it just expands the statement essentially cloning it, it doesn't trigger it
    – revelt
    Mar 5, 2018 at 13:43
7

You can plan ahead during command execution (provided it isn't interactive) and enter !! which will execute the previous command again. This works e.g. during ping -c 5.


You can also define a function in bash:

function repeat { "$@"; "$@"; }

To persist it, store it in ~/.bashrc.

Then, you can run your command like this:

repeat ping -c5 heise.de

If it's a specific command you want to repeatedly execute (and not e.g. any command), you can replace "$@" in that snippet with your actual command, and name the function e.g. repeat_ping instead.


To make it an infinite loop, you can do what @Dennis suggests. I recommend you add a waiting period if you intend to use this in an interactive shell, like this:

function repeat { while 1 ; do "$@" ; sleep 1 ; done; }

Otherwise it's rather inconvenient to abort this infinite loop using Ctrl-Z.

3
  • Please see the edit to the original question.
    – user107012
    Nov 27, 2011 at 13:30
  • 6
    @calcifer These executions wait until the program call returns. Does your program detach from the shell and return before it quits?
    – Daniel Beck
    Nov 27, 2011 at 13:31
  • My bad, I thought this (and all the other answers) will either fork the process or re-execute it just once, neither of which is wanted. So yes, this answer works. Thanks.
    – user107012
    Nov 27, 2011 at 19:48
5

Give a while loop a boolean condition such as follows:

#!/bin/bash

while true; do

    do_something && wait

done

This will execute over and over until bash receives a signal to terminate the process. Usually in the form of ctrl+c.

You can also use the watch command to run a script repeatedly as well. For instance a simple clock in your bash terminal using watch could look like:

$ watch -t -n1 date +%T

The -t option tells watch to not display a title of the process it is running. This gives you a clean output of only the command that is being repeated. The -n1 option tells watch to repeat every n seconds. In this case, -n1 will be intervals of 1 second. Then the date +%T command shows the time at the time of command completion. Doing this command will give you an active clock in your terminal.

And then one more method that isn't in any of the other answers would be an infinite function call.

do_something() { do_something }; do_something && wait

This is essentially the same as the boolean while loop only using recursive function calls.

(edit) For keeping your machine's resources in mind, I have added the && wait so that each time a process is run, the loops will "wait" until that process finishes with exit status 0 before the next iteration. This is useful in an interactive shell script.

9
  • 1
    There is a while loop example but it isn't using a boolean true syntax. There is a watch example but it doesn't give many useful syntax. I am expounding on these for whomever it may help. I wanted to give some practical usefulness to these. The while loop boolean can also be false and not execute until an untrue condition is met. It is quite handy.
    – user723485
    Apr 29, 2017 at 23:10
  • 1
    @Spittin'IT Added a method that is not used in other answers for your convenience.
    – user723485
    Apr 29, 2017 at 23:16
  • Fair enough and I understand... I was just commenting as I went thru the review module but nice edit and follow up!! Apr 29, 2017 at 23:17
  • How does if keep re-executing? Apr 29, 2017 at 23:22
  • Good point Kamil. Forgot to make it recursive lol. Fixed in edit using a function calling itself in the if statement.
    – user723485
    Apr 29, 2017 at 23:38
1

I'm feeling saucy today.

Read from one of the infinite streams and pipe it to xargs

cat /dev/zero | xargs --null echo hello there

If you need to put a little bit of a break in there you will likely need to execute sh

cat /dev/zero | xargs --null sh -c "echo hello there; sleep 3"
0

This is another method I use to repeat a command in bash. This might sound silly to some as it does not involve writing a script and might be known to many. But I think it is worth mentioning as it is quick and beginner-friendly, in the sense that there is not much syntax to remember. I've only tested this in gnome-terminal of Ubuntu and other terminals might not support this.

  1. Enter the command in terminal once.
  2. Select the command including newline character with mouse.
  3. Copy the selection using Ctrl-Insert or using context menu (usually accessed with right click).
  4. Use Shift-Insert to paste as many times as you want to run the command.

You don't have to wait to paste until each command finishes. The pasted commands get into a queue and they execute one after another.

You must log in to answer this question.