How to run a command 1 out of N times in Bashd Emt x Y
I want a way to run a command randomly, say 1 out of 10 times. Is there a builtin or GNU coreutil to do this, ideally something like:
chance 10 && do_stuff
where do_stuff
is only executed 1 in 10 times? I know I could write a script, but it seems like a fairly simple thing and I was wondering if there is a defined way.
-
This is a fairly good indicator that your script is probably getting too-out-of-hand for bash to continue being a reasonable choice. You should consider a more full fledged programming language, perhaps a scripting language like Python or Ruby. – Alexander 1 hour ago
5 Answers
In ksh, bash, zsh, yash or busybox sh:
[ "$RANDOM" -lt 3277 ] && do_stuff
The RANDOM
special variable of the ksh
, bash
, yash
,zsh
and busybox shells produces a pseudo-random decimal integer value between 0 and 32767 every time it’s evaluated, so the above gives (close to) a one-in-ten chance.
-
1The formula for an atbitrary number of parts is
[[ $RANDOM -lt $((32767/parts+1)) ]] && do_stuff
. Better use[[ ]]
to avoid that IFS affects the result. – Isaac 13 hours ago
Non-standard solution:
[ $(date +%1N) == 1 ] && do_stuff
Check if the last digit of the current time in nanoseconds is 1!
-
That's awesome. – Eric Duminil 20 hours ago
-
1You have to make sure that the call
[ $(date +%1N) == 1 ] && do_stuff
does not occur at regular intervals, otherwise the randomness is spoiled. Think ofwhile true; do [ $(date +1%N) == 1 ] && sleep 1; done
as an abstract counterexample. Nonetheless, the idea of playing with the nanoseconds is really good, I think I will use it, hence +1 – XavierStuvw 16 hours ago -
1@XavierStuvw I think you'd have a point if the code was checking seconds. But nanoseconds? It should appear really random. – Eric Duminil 5 hours ago
An alternative to using $RANDOM
is the shuf
command:
[[ $(shuf -i 1-10 -n 1) == 1 ]] && do_stuff
will do the job. Also useful for randomly selecting lines from a file, eg. for a music playlist.
I'm not sure if you want randomness or periodicity ... For periodicity:
for i in `seq 1 10 100`; do echo $i;done
1
11
21
31
41
51
61
71
81
91
You can mix it with the "$RANDOM" trick above to produce something more chaotic, for instance:
for i in seq 1 1000 $RANDOM
; do echo $i;done
HTH :-)
Improving upon the first answer and making it much more obvious what you are trying to achieve:
[ $[ $RANDOM % 10 ] == 0 ] && echo "You win" || echo "You lose"