60

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.

  • 1
    You still aren't clear. It'd help if you mentioned what program you're executing. – Daniel Beck Nov 27 '11 at 13:38
  • 1
    -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 '11 at 20:04
37

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

while :
    do
        command
done
  • 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 '11 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 '11 at 13:39
  • @calcifer this is an infinite loop. it keeps repeating until the end of time (well, until the script is terminated anyways) – Nate Koppenhaver Nov 27 '11 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 '11 at 19:48
  • one line version: while true; do echo 'Hit CTRL+C'; sleep 1; done, thanks to cyberciti.biz/faq/bash-infinite-loop – jk2K Nov 11 '18 at 16:18
103

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.

  • Please see the edit to the original question. – user107012 Nov 27 '11 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 '11 at 13:34
  • I didn't know that about fork, thanks. – user107012 Nov 27 '11 at 19:54
  • I can't see any output using this method. – Raffi Khatchadourian Mar 8 '16 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 '16 at 1:40
17

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)

  • 1
    Sorry, I wasn't clear enough. I need to keep re-executing it over and over again, not just once. – user107012 Nov 27 '11 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 '15 at 21:11
  • ; !# didn't work on ZSH, it just expands the statement essentially cloning it, it doesn't trigger it – revelt Mar 5 '18 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.

  • Please see the edit to the original question. – user107012 Nov 27 '11 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 '11 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 '11 at 19:48
4

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.

  • 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 '17 at 23:10
  • 1
    @Spittin'IT Added a method that is not used in other answers for your convenience. – user723485 Apr 29 '17 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!! – Pimp Juice IT Apr 29 '17 at 23:17
  • How does if keep re-executing? – Kamil Maciorowski Apr 29 '17 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 '17 at 23:38
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.

0

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"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy