1

I would like to run a command line program again and again inside an infinite loop.
The program will occasionally output different data.

Whenever the new data is output, I would like the previous data to be overwritten.

Example:
The following program will output the time of day.

#include <stdio.h>
#include <time.h>

int main (){
  time_t rawtime;
  struct tm * timeinfo;
  time ( &rawtime );
  timeinfo = localtime ( &rawtime );
  printf ( "Current local time and date: %s", asctime (timeinfo) );
}

The naive approach would be the following:

while true; do ./main; clear; done

Of course, this will clear the screen every run, and cause a flicker.
enter image description here

I could certainly pipe it into a custom program that only refreshes output on change,
but I was hoping to find a solution using standard linux commands
(or Bash language features).

The program output could be multi-line, so returning(/r) and re-writting is not an option.

Trevor Hickey
  • 36,288
  • 32
  • 162
  • 271
  • 1
    Not quite what you asked, but if you are allowed to modify the original program you could have it clear the line itself. This can avoid flicker, because it only does it whenever it has new output to print (and you get to control when it flushes). This is how commandline programs that "replace" lines of output work: http://stackoverflow.com/questions/1508490/how-can-i-erase-the-current-line-printed-on-console-in-c-i-am-working-on-a-lin – Chris Kitching Sep 12 '16 at 21:40
  • @ChrisKitching I'm looking for a drop-in replacement for any program. For example, I'd be able to use it with `ls` and such too. It could be done through a pipe or the program could take another program name as an argument. Whatever works. It could multi-line output too! – Trevor Hickey Sep 12 '16 at 21:43
  • 1
    Could you try `watch --interval=1 --no-title ./main` ? Not exactly identical but maybe close enough? – fvu Sep 12 '16 at 21:44
  • @fvu That works perfectly. – Trevor Hickey Sep 12 '16 at 21:55
  • Well, if @GöranUddeborg would integrate them in his answer that would be great then, no? :) – fvu Sep 12 '16 at 21:56

2 Answers2

4

If you have the command watch available, you could use that. Simply type

watch ls
Göran Uddeborg
  • 351
  • 3
  • 10
  • 1
    You may want to integrate my comments, I think with them the output is closer to what OP may be looking after. – fvu Sep 12 '16 at 21:54
  • @fvu Yeah, your comment is a better fit. `watch` is the solution. `--no-title` is preferred. If the interval is left out, it appears to update as frequently as possible, but adding an interval may be helpful later. Thanks. – Trevor Hickey Sep 12 '16 at 21:57
  • @TrevorHickey that's odd - I tested here on a Centos box using `watch --no-title date` and it looked like the refresh took place every two seconds that way, which is why I added the interval. Maybe it's distro dependent? – fvu Sep 12 '16 at 22:00
  • The Fedora version of `watch` also updates every second second. :) It is documented in the manual page. – Göran Uddeborg Sep 12 '16 at 22:16
1

This ought to do it:

while true; do LINE=$(date) | echo -en "\r$LINE"; done

Replace date with the program of interest, but it makes a cool demo.

Using a pipe in this way prevents the clearing from taking place until there is new output to print, and makes clearing and printing new output happen in one step.

Caveat: This won't clear correctly if something prints more than one line. On the other hand, it doesn't nuke your entire terminal screen like watch or clear does.

Chris Kitching
  • 2,559
  • 23
  • 37