bash has many things that just works automagically. Did you know it has a built-in pseudorandom number generator? Let’s play games!

Before continuing, note that this is pseudo-randomization with a small footprint. DO NOT use it for security, scrambling, passwords, or anything even scarcly security related.

Matching a message
Image by XKCD, CC-2.5

The random function in bash is called by the magic variable RANDOM. It gives you a more or less random integer between 0 and 32767.

 $ echo $RANDOM
 720
 $ echo $RANDOM
 29582

This seems optimized for silly games:

 #!/bin/bash
 echo -n "Let's play a game: Pick a number between 0 and 32767: "
 read a
 if (( RANDOM == a )); then
   echo AMAZING, your answer is correct
 else
   echo Sorry, that was wrong
 fi

Note that unsetting the variable removes the magic for the rest of the shell session.

 $ unset RANDOM
 $ RANDOM=42
 $ echo $RANDOM
 42
 $ echo $RANDOM
 42

You may format the output by using the modulo operator % and the built-in integer arithmetics in bash, called by ((expression)):

 # A number 0-9
 $ echo $(( RANDOM % 10 ))
 4
 
 # A number 0-99
 $ echo $(( RANDOM % 100 ))
 67
 
 # A number 0-999
 $ echo $(( RANDOM % 1000 ))
 783

So we can make our game a bit more interesting:

 #!/bin/bash
 prs=("paper" "rock" "scissors")
 echo -n "Get ready Player 1: Choose ${prs[@]}: "
 read a
 
 case $a in
   "paper") a=0;; "rock")  a=1;; "scissors") a=2;;
   *) echo No cheating; exit 1 ;;
 esac
 
 echo "You chose ${prs[$a]}"
 
 b=$(( RANDOM % 3 ))
 echo "The computer choose ${prs[$b]}"
 
 if (( a == b )); then echo "A draw!"; exit 0; fi
 
 case "$a$b" in
   01) winner="You";;
   02) winner="The computer";;
   10) winner="The computer";;
   12) winner="You";;
   20) winner="You";;
   21) winner="The computer";;
 esac
 
 echo "Winner: $winner"

One might think that, since RANDOM is a number between 0 and 32k, it would be skewed away from the decimal system, so let’s check that: Picking 10000 numbers between 0 and 999, the mean should be about 499,5.

 for n in 1 2 3 4 5; do for i in $(seq 1 10000); do
   echo $((RANDOM%1000));
 done | awk '{SUM+=$1} END{print SUM/10000}'; done
 
 498.253
 501.122
 495.839
 503.898
 498.537

So, it seems this is good enough for most purposes.

For a testing purpose, I need a tree of directories with variable depth subdirectories and some diverse data:

 cd "$(mktemp -d)"
 for n in $(seq 1 100); do
   depth=$((RANDOM%10))
   for i in $(seq 1 $depth); do
     dir=dir$((RANDOM%10))
     mkdir -p $dir;
     pushd $dir;
   done;
   echo $((RANDOM%100)) > file$((RANDOM%100));
   for i in $(seq 1 $depth); do popd; done;
 done;
 find; echo; ls

Some times I need to test a script or a function with just true or false values. RANDOM can be used for this as well:

 for i in $(seq 1 10); do
   if (( RANDOM %2 )); then
     echo true
   else
     echo false
   fi
 done

 false
 true
 true
 false
 false
 false
 true
 false
 true
 false

To sum up: Bash has a handy random number generator, called by the magic variable RANDOM. It should NOT be used anything related to security. Also, make sure you do not use the variable name RANDOM for other purposes, as the behaviour will be, well, random.