Alan H.
Alan H.

Reputation: 16568

How can I write a tiny Bash shell script to repeat an action every 5 seconds?

I want to copy a file from one location to another every five seconds. I don’t want to set up a cronjob because this is only temporary and needs to be fully under my control.

Can I write a .sh that will do this?

(I’m on Mac OS X.)

Upvotes: 16

Views: 35376

Answers (7)

Keith Thompson
Keith Thompson

Reputation: 263277

One potential problem that most of the answers share (including the ones using the watch command) is that they can drift. If that's not a problem, then don't worry about it, but if you want to the command to be executed as closely as possible to once every 5 seconds, read on.

This:

while : ; do cp from_file to_file ; sleep 5 ; done

will sleep for 5 seconds between file copies -- which means that if the copy takes 2 seconds, the loop will run every 7 seconds.

If instead you want to start the cp command every 5 seconds regardless of how long it takes, you can try something like this:

while : ; do
    now=$(date +%s) # current time in seconds
    remaining=$((5 - now % 5))
    sleep $remaining
    cp from_file to_file
done

This computes the seconds remaining until the next multiple of 5 (1 to 5 seconds) and sleeps for that long, so as long as the cp command finishes in less than 5 seconds, it will run it every 5 seconds. If it takes 2 seconds, it will sleep 3 seconds before running it again, and so forth.

(If the command takes longer than 5 seconds, it will skip one or more iterations. If you want to avoid that -- which means you might have two or more cp commands running in parallel -- you can run the cp command in background: cp from_file to_file &.)

You can combine the computations into a single expression if you like. I used named variables for clarity.

Upvotes: 4

Alex Nolasco
Alex Nolasco

Reputation: 19456

One liner,

 while :; do cp from_file to_file; sleep 5; done

Upvotes: 2

Sage Mitchell
Sage Mitchell

Reputation: 1583

The watch command is a good option. If you end up needing more control you can use a while loop:

while [ 1 ]
do
  cp source dest
  sleep 5s
done

Upvotes: 21

Sean
Sean

Reputation: 97

not sure if this will work, but you could try it, basically it is an infinite loop, so you would have to terminate the script manually or add a filter for say the q key, when pressed sets copyFiles to 0

copyFile = 1
while [ ${copyFile} -eq 1 ]
do
    echo "Copying file..."
    cp file /other/location
    echo "File copied.  Press q to quit."
    read response
    [ "$response" = "q" ] && copyFile = 0
    sleep 5
done

Upvotes: 1

David Yaw
David Yaw

Reputation: 27864

while true
do
    cp file /other/location
    sleep 5
done

You don't even need to write a script for this, just type while true; do cp file /other/location; sleep 5; done at the bash prompt.

Upvotes: 16

barti_ddu
barti_ddu

Reputation: 10299

Perhaps watch will do:

watch -n 5 date

Upvotes: 11

ngen
ngen

Reputation: 8966

Use the watch command.

Source

Upvotes: 3

Related Questions