This is a follow on from my previous thread :- Passing date command into a variable?

Ok so effectively I would like /dev/urandom to generate 4 digits for me. And place them into a variable.

Here is an example of my bash script :-

for (( c=0; c<=10; c++))
        a="$(tr -dc '[:digit:]' < /dev/urandom | fold -w 4)"

        echo $a

The only reason I wish to "Echo" the results is so I can actually see that /dev/urandom has generated 4 digits for me correctly.

For my bash script I wish to make, I need to do this programmatically as I wish to do further operation's on the generated results.

So I need not "Echo" the results. so is a="$(tr -dc '[:digit:]' < /dev/urandom | fold -w 4)"

Actually placing 4 random digits into the variable "a"? when I Echo "a" from my script I just get a hanging console and have to use "CTRL+C" to bring my console back.

All I am trying do is place 4 random digits from /dev/urandom into a variable.

I m a new to bash scripting so all advice welcome and thank you in advanced for any help or suggestions.

2 Answers 2


If you don't need security, you can use bash's built-in RANDOM variable. To get a random number between 0 and 9999 inclusive, $((RANDOM % 10000)) gives a small bias towards values less than 767, because the values of $RANDOM are uniform in the range [0, 32767]. To get a uniform distribution, and put leading zeros:

while a=$((RANDOM + 10000)); ((a <= 39999)); do :; done

Note again that this is not applicable anywhere security is a concern. The output from $RANDOM is not unpredictable.

If you do need security, then /dev/urandom is the right place to get random data. Calling fold is unnecessary on most current unices: you can grab 4 characters with head -c.

a=$(</dev/urandom tr -dc 0-9 | head -c 4)

head -c is not POSIX and not present on OpenBSD, but it's present in other BSD and on Linux (both with GNU coreutils and BusyBox).

If you need portability to systems that don't have head -c, then fold -w 4 | head -n 1 is a good replacement that's POSIX standard. Just note that you do need the head call, otherwise fold will keep outputting lines of 4 digits forever.


fold will just fold the infinite stream of digits and thus a is being defined indefinitely. You will need to add a terminating command, simplest head:

 a="$(tr -dc '[:digit:]' < /dev/urandom | fold -w 4 | head -n1)"

Just compare the bahaviour of these two commands

tr -dc '[:digit:]' < /dev/urandom | fold -w 4  
tr -dc '[:digit:]' < /dev/urandom | fold -w 4 | head -n1

The first one will show the infinite stream of 4-digit random numbers, while the second will abort after one line.

  • Thank you!, Is there anyway I can reward you? I have been stressing over this for a week in my head and googling like crazy. Again a big thank you! shanzem@Shanzem-Laptop:~$ ./me2.sh 6833 3491 2564 0628 8361 3693 3398 3753 4049 8340 2090 shanzem@Shanzem-Laptop:~$ Finally got my result.
    – Shanzem
    Jun 22, 2021 at 9:16
  • @Shanzem just mark it as accepted answer as you did. This is the concept of this community. Be aware that your script overwrites a in each run of the loop. For getting it in a matrix, use e.g. a[i]="$( ... )" Or simpler skip the loop and run: a=( $( .... | head -n 10 ) ) and call via ${a[0]}, ${a[1]} ... etc. bash indexing starts at 0.
    – FelixJN
    Jun 22, 2021 at 9:26
  • Understood and again thank you so much :).
    – Shanzem
    Jun 22, 2021 at 9:30

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.