On my machine I need to execute a cycle that iterates 1 simple command that must have a delay expressed in fractions of second.

Let's say that I need:

  • to save a file with an increasing enumaration ( file-0, file-1, file-2, ... ) generate by something trivial for this example like time > file-$x
  • I need to do this every 1/70 of second (as an example) because I would like to express my time with fractions of second.

How can I be really precise and have everything expressed with a bash script?

The fraction can generate an indeterminable quantity, I need to be precise and so I need at least 4-5 decimals.


To convert from fractions to decimals in bash, do something like

myvar=$(echo "scale=4; 5/10" | bc)

Then, to do a loop on that value,

for i in $(seq 1 1000); do sleep $myvar; done

My sleep implementation on Debian (GNU) seem to accept decimal sleep values.


With that kind of precision (4-5 decimal places), you're going to want something like a perl script or a compiled program; the overhead of calling any program within the loop is going to add a lot of jitter. Calling sleep itself will take a few milliseconds.

Consider the following, a 1/10,000ths of a second sleep, done 1000 times:

time for i in $(seq 1 1000); do sleep 0.0001; done

real    0m2.099s
user    0m3.080s
sys     0m1.464s

The expected result would be 1/10th of a second. Sleep has nowhere near the tolerances you want.


using perl's Time::HiRes, 1000*1000 microseconds:

my $i=0;
for($i=0;$i<=1000;$i++) {

real    0m1.133s
user    0m0.024s
sys     0m0.012s

gives us much closer to a second.

  • if it's not possible to achieve 4-5 decimals i would take the best possible result as an alternative, but my point is that i need to express this in fractions, not decimals or seconds. – user1717079 Oct 12 '12 at 21:13
  • It'd be utterly trivial to convert a fraction to a decimal in any scripting language, including bash. eg echo "scale=4; 5/10" | bc – Rob Bos Oct 12 '12 at 21:18
  • now i have got how to convert the expression, the problem now is that a simple bash it's really slow and can't simply keep up with this frequency... – user1717079 Oct 12 '12 at 21:26
  • Yeah, if you want anything much more precise than about 1/10th of a second, you'll probably want perl or python so as to avoid the program calling overhead within the loop. – Rob Bos Oct 12 '12 at 21:28

Maybe you can simply run

sleep 0.7


man 1 sleep

on my archlinux distro :

DESCRIPTION Pause for NUMBER seconds. SUFFIX may be 's' for seconds (the default), 'm' for minutes, 'h' for hours or 'd' for days. Unlike most implementations that require NUMBER be an integer, here NUMBER may be an arbitrary floating point number. Given two or more arguments, pause for the amount of time specified by the sum of their values.

  • sleep allows fractions ? can you offer a complete example with a fake loop ? – user1717079 Oct 12 '12 at 20:59
  • 0.7 it's not a fraction that express my problem ... my problem is about granularity; think about 1/3 and try to be precise with sleep. – user1717079 Oct 12 '12 at 21:02

Spawning a process and load a new executable in it is likely to take a few miliseconds, so that kind of precision doesn't really make sense. Also note that CPU time on many systems is allocated to processes by slices of up to 10ms.

Having said that, some sleep implementations take fractional numbers of seconds, and both zsh and ksh93 can make their $SECONDS special variable fractional with typeset -F SECONDS.

Example (zsh):

$ typeset -F SECONDS=0; for ((i=1; i<=70; i++)); do sleep $((1./70)); date +%s.%N; done | { head -n3;echo ..;tail -n3; }; echo $SECONDS

Oops, it drifted. You can adjust the sleeping time based on $SECONDS:

$ typeset -F SECONDS=0; for ((i=1; i<=70; i++)); do sleep $((i/70. - SECONDS)); date +%s.%N; done | { head -n3;echo ...;tail -n3; }; echo $SECONDS

Those 2 extra miliseconds are probably to be accounted to running the last sleep and date commands.

Also note that zsh has a zselect builtin with timeout expressed in hundredth of a second. And ksh93 has sleep built in (and accepts floating points) and its printf can print date/times.

$ typeset -F SECONDS=0; for ((i=1; i<=70; i++)); do ((i<4 || i>67)) && printf '%(%S.%N)T\n' now; sleep $((i/70.-SECONDS)); done; echo $SECONDS

If you want anything more precise, you'll probably want a real time operating system or an operating system with real time capabilities and certainly not use a shell.

  • sleep 1/70 not allowed on my machine ... – user1717079 Oct 12 '12 at 21:07
  • not even near to what i want to achieve, how i can execute things faster ? – user1717079 Oct 12 '12 at 21:19
  • Sorry, by fractional, I didn't mean expressed as n/m where n and m are integers, but as decimals with a fractional part. I suppose you could also call them decimal floating point numbers though I'm not sure about the proper English terminology – Stéphane Chazelas Oct 12 '12 at 21:20
  • i think that i'm going to avoid the of the shell ... – user1717079 Oct 12 '12 at 21:27
  • The answerer is right. Shells and processes are usually not well suited to millisecond resolution. For reliable performance, you'll need to compile a program that calls usleep(3) or the like -- and you may need to recompile your kernel with a different configuration, as well; or at least feed different parameters to your kernel's runtime scheduler. This is nontrivial to do. A standard Debian installation with a standard kernel has limited realtime capabilities. Still, you might want to check out the nice(1) command; it might help. – thb Sep 12 '16 at 0:43

If your shell's sleep doesn't accept fraction, use perl.

sleep_fraction() {
  /usr/bin/perl -e "select(undef, undef, undef, $1)"

sleep_fraction 0.01428

If you need to find out the fraction, use echo "scale=5; 1/70" | bc


Under Alpine Linux (Busybox) you can loop for microseconds with usleep 10 (equivalent to 0.00001 of a second)

GNU sleep supports fractions of a second: sleep 0.00001

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.