A bash script for random quote on shell login

With a few lines of bash scripting you can print a random quote every time a new terminal is launched.

First things first: the quotes. These should be stored in a text file; every line contains a single, entire quote — use the \n escape character to signal that a quote should be split on multiple lines.
Here is an example of what the contents of said file might look like, with four quotes from different films:

A wizard is never late, nor is he early, he arrives precisely when he means to.
May the Force be with you.
All that is gold does not glitter\nNot all those who wander are lost.
Keep your friends close, but your enemies closer.

Notice the use of \n in the third one.

Now that we have the quotes, we can generate a random integer that corresponds to a line inside the file — i.e. a random quote.
In Bash, a random integer can be obtained with the $RANDOM variable. This, however, will give a number in the range 0 to 32767 which, unless you have a file of 32767 lines exactly[1], is not ideal.

echo $RANDOM   # output: 10226

We need to limit our randomness between 1 and our maximum: the number of quotes.
First, let's count the number of lines in our file:

num_lines=$(wc -l < /path/to/quotes.txt)

Then, let's generate a random integer inside this range:

random_num=$(( RANDOM % num_lines + 1 ))

The addition of +1 is needed to handle two edge cases: when $RANDOM is either 0 or equal to $num_lines. In these scenarios the modulo operation would yield 0, which is an invalid line number. Additionally, the +1 ensures that the maximum range value, $num_lines (the last line in the file) can be obtained.

All that is left now is to extract the corresponding line from the file and print it:

line=$(head -$random_num /path/to/quotes.txt | tail -1)
printf "%b\n" "$line"

You can put these lines in a script or directly in the shell's config file (e.g. bashrc, zshrc, ...) and a different quote will appear above the first prompt every time a new shell is opened.

future improvements

which you might find useful and/or fun but I'm too lazy to show:

  • put the file path in a variable
  • check that the file exists
  • check that the file is not empty
  • customize the printf with quotes, italic font...
  • add a check to avoid getting the same quote twice in a row

One thing I realized while writing is that the code won't work if the file is more than 32767 lines long. By "won't work" I mean it will never access those exceeding lines.
And even though I doubt anyone could ever collect more than 30 thousands quotes, I thought it would be nice to address this problem.
One way to fix it would be:

random_num=$(( RANDOM * num_lines / 32767 + 1 ))

  1. Less than that is a waste, more would be useless since higher line numbers would never be generated. ↩︎