330

Is it possible in Linux command line to have a command repeat every n seconds?

Say, I have an import running, and I am doing

ls -l

to check if the file size is increasing. I would like to have a command to have this repeat automatically.

Pang
  • 9,564
  • 146
  • 81
  • 122
Marty Wallace
  • 34,046
  • 53
  • 137
  • 200

14 Answers14

582

Watch every 5 seconds ...

watch -n 5 ls -l

If you wish to have visual confirmation of changes, append --differences prior to the ls command.

According to the OSX man page, there's also

The --cumulative option makes highlighting "sticky", presenting a running display of all positions that have ever changed. The -t or --no-title option turns off the header showing the interval, command, and current time at the top of the display, as well as the following blank line.

Linux/Unix man page can be found here

Rawkode
  • 21,990
  • 5
  • 38
  • 45
131
while true; do
    sleep 5
    ls -l
done
Oleksandr Kravchuk
  • 5,963
  • 1
  • 20
  • 31
  • 12
    `watch` also has the unfortunate side effect of clearing the screen, so sometimes the loop is useful. Which to use depends on the desired format of the output. – William Pursell Nov 27 '12 at 21:53
  • I'll usually do the loop, but do it on one line. Watch looks much better, though, I'll have to switch to that. – Don Branson Nov 27 '12 at 21:54
  • 1
    @MartyWallace This can be done with the command line (the while loop). – keyser Nov 27 '12 at 21:55
  • It's worth noting you can use `--differences` to have them highlighted (If you're concerned about the repainting of the terminal) – Rawkode Nov 27 '12 at 21:57
  • This is better than `watch`. Watch does not work for example when you want to generated random number in each invocation, e.g. `watch -n 1 echo ${RANDOM}`. The random will only get called once. – Marcin Jan 12 '20 at 12:48
99

"watch" does not allow fractions of a second in Busybox, while "sleep" does. If that matters to you, try this:

while true; do ls -l; sleep .5; done
mikhail
  • 5,019
  • 2
  • 34
  • 47
44

sleep already returns 0. As such, I'm using:

while sleep 3 ; do ls -l ; done

This is a tiny bit shorter than mikhail's solution. A minor drawback is that it sleeps before running the target command for the first time.

Asclepius
  • 57,944
  • 17
  • 167
  • 143
Sebastian Wagner
  • 2,308
  • 2
  • 25
  • 32
20

If the command contains some special characters such as pipes and quotes, the command needs to be padded with quotes. For example, to repeat ls -l | grep "txt", the watch command should be:

watch -n 5 'ls -l | grep "txt"'

jonathanzh
  • 1,346
  • 15
  • 21
16

Running commands periodically without cron is possible when we go with while.

As a command:

while true ; do command ; sleep 100 ; done &
[ ex: # while true;  do echo `date` ; sleep 2 ; done & ]

Example:

while true
do echo "Hello World"
sleep 100
done &

Do not forget the last & as it will put your loop in the background. But you need to find the process id with command "ps -ef | grep your_script" then you need to kill it. So kindly add the '&' when you running the script.

# ./while_check.sh &

Here is the same loop as a script. Create file "while_check.sh" and put this in it:

#!/bin/bash
while true; do 
    echo "Hello World" # Substitute this line for whatever command you want.
    sleep 100
done

Then run it by typing bash ./while_check.sh &

Ranjithkumar T
  • 1,886
  • 16
  • 21
  • Isn't the last & , same as writing the command without & in the end , but calling the script with & : bash ./while_check.sh & ? – ransh Sep 15 '16 at 17:49
  • @ransh : We can run the script ./while_check.sh & so we can get the process id immediately, when we add the & in script and just run the script without & , we didn't get any process id but it will run background, as i edited we need ps command to get the process id if we need to stop the script. – Ranjithkumar T Sep 22 '16 at 05:29
  • If you wish, you can modify the script to `echo $!` after each background process is launched — that's the PID of the last child process launched in the background. – Jonathan Leffler Sep 22 '16 at 05:49
  • `echo \`date\` ` is just a poor and slightly buggy way to write just `date`. (The bug has to do with the lack of quoting of the argument to `echo`.) See also [useless use of `echo`.](http://www.iki.fi/era/unix/award.html#echo) – tripleee Jan 12 '19 at 20:29
8

watch is good but will clean the screen.

watch -n 1 'ps aux | grep php'
Eduardo
  • 81
  • 1
  • 1
7

If you want to do something a specific number of times in zsh:

repeat 300 (command1; command2) && sleep 1.5

Note that repeat is not a bash command.

General Grievance
  • 4,555
  • 31
  • 31
  • 45
brightball
  • 923
  • 13
  • 11
6

If you want to avoid "drifting", meaning you want the command to execute every N seconds regardless of how long the command takes (assuming it takes less than N seconds), here's some bash that will repeat a command every 5 seconds with one-second accuracy (and will print out a warning if it can't keep up):

PERIOD=5

while [ 1 ]
do
    let lastup=`date +%s`
    # do command
    let diff=`date +%s`-$lastup
    if [ "$diff" -lt "$PERIOD" ]
    then
        sleep $(($PERIOD-$diff))
    elif [ "$diff" -gt "$PERIOD" ]
    then
        echo "Command took longer than iteration period of $PERIOD seconds!"
    fi
done

It may still drift a little since the sleep is only accurate to one second. You could improve this accuracy by creative use of the date command.

mcote
  • 634
  • 6
  • 6
  • Thanks.. but I have 2 questions, 1- where to save that code? in other word, In which path should I put the file containing that script? that makes it run automatically?! 2- how to include php file in ( # do command ) instead of typing all my code there? – Hossam Feb 01 '18 at 09:46
  • 1
    I suggest you research a bit on bash scripts so you can understand the basics of how to run them and so forth. – mcote Mar 18 '18 at 00:47
4

You can run the following and filter the size only. If your file was called somefilename you can do the following

while :; do ls -lh | awk '/some*/{print $5}'; sleep 5; done

One of the many ideas.

Asclepius
  • 57,944
  • 17
  • 167
  • 143
Valentin Bajrami
  • 229
  • 2
  • 14
3

A concise solution, which is particularly useful if you want to run the command repeatedly until it fails, and lets you see all output.

while ls -l; do
    sleep 5
done
2

To minimize drift more easily, use:

while :; do sleep 1m & some-command; wait; done

there will still be a tiny amount of drift due to bash's time to run the loop structure and the sleep command to actually execute.

hint: ':' evals to 0 ie true.

math
  • 151
  • 3
1
watch -n 5 'ls -l 

Will Runls -l command after every 5s

Output :-

Every 5.0s: ls -l                                                                                                      Fri Nov 17 16:28:25 2017

total 169548
-rw-rw-r--  1 sachin sachin     4292 Oct 18 12:16 About_us_Admission.doc
-rw-rw-r--  1 sachin sachin      865 Oct 13 15:26 About_us_At_glance.doc
-rw-rw-r--  1 sachin sachin     1816 Oct 13 16:11 About_us_Principle.doc
-rw-rw-r--  1 sachin sachin     1775 Oct 13 15:59 About_us_Vission_mission.doc
-rw-rw-r--  1 sachin sachin     1970 Oct 13 16:41 Academic_Middle_school.doc
-rw-rw-r--  1 sachin sachin      772 Oct 16 16:07 academics_High_School.doc
-rw-rw-r--  1 sachin sachin      648 Oct 16 13:34 academics_pre_primary.doc
-rw-rw-r--  1 sachin sachin      708 Oct 16 13:39 academics_primary.doc
-rwxrwxr-x  1 sachin sachin     8816 Nov  1 12:10 a.out
-rw-rw-r--  1 sachin sachin    23956 Oct 23 18:14 Ass1.c++
-rw-rw-r--  1 sachin sachin      342 Oct 23 22:13 Ass2.doc
drwxrwxr-x  2 sachin sachin     4096 Oct 19 10:45 Backtracking
drwxrwxr-x  3 sachin sachin     4096 Sep 23 20:09 BeautifulSoup
drwxrwxr-x  2 sachin sachin     4096 Nov  2 00:18 CL_1
drwxrwxr-x  2 sachin sachin     4096 Oct 23 20:16 Code
drwxr-xr-x  2 sachin sachin     4096 Nov 15 12:05 Desktop
-rw-rw-r--  1 sachin sachin        0 Oct 13 23:12 doc
drwxr-xr-x  4 sachin sachin     4096 Nov  6 21:18 Documents
drwxr-xr-x 27 sachin sachin    12288 Nov 17 13:23 Downloads
-rw-r--r--  1 sachin sachin     8980 Sep 19 23:58 examples.desktop
Community
  • 1
  • 1
HeadAndTail
  • 804
  • 8
  • 9
0

I created a shell alias that will watch the commands passed to it every x number of seconds. The commands can be separate arguments or separated by semicolons.

# execute commands at a specified interval of seconds
function watch.command {
  # USAGE: watch.commands [seconds] [commands...]
  # EXAMPLE: watch.command 5 date
  # EXAMPLE: watch.command 5 date echo 'ls -l' echo 'ps | grep "kubectl\\\|node\\\|npm\\\|puma"'
  # EXAMPLE: watch.command 5 'date; echo; ls -l; echo; ps | grep "kubectl\\\|node\\\|npm\\\|puma"' echo date 'echo; ls -1'
  local cmds=()
  for arg in "${@:2}"; do
    echo $arg | sed 's/; /;/g' | tr \; \\n | while read cmd; do
      cmds+=($cmd)
    done
  done
  while true; do
    clear
    for cmd in $cmds; do
      eval $cmd
    done
    sleep $1
  done
}

https://gist.github.com/Gerst20051/99c1cf570a2d0d59f09339a806732fd3

Andrew
  • 3,733
  • 1
  • 35
  • 36