Page Body

How to Randomly Select Directory Objects With Bash

Making decisions can be hard. Sometimes, it is advantageous (and fun) to introduce a little randomness into this process.

Over time, you may find that you have a large number of digital items (e.g., PDF research papers, presentation videos, ebooks) to review. Whatever they are, you may not know where you should direct your attention to next.

It could be nice to let chance guide you, and Bash can help.

Note: If you are not familiar with the GNU/Linux command line interface, review the Conventions page before proceeding.

Generating A Random Number From a Range

We assume that you have organized your content into directories. Each directory contains either files or subdirectories. We want to generate a random number in the range of zero to the number of items in the target directory (minus one, since we are starting at zero).

The find and wc commands can help us:

find ex_dir -mindepth 1 -maxdepth 1 ! -name '.*' | wc -l

  • -mindepth 1 ensures that we do not include ex_dir itself in the find output.
  • -maxdepth 1 ensures that we do not recurse into any subdirectories that are present in ex_dir.
  • ! -name '.*' ensures that we do not include any hidden directory items.
  • wc -l counts the number of lines in find's output (i.e., it determines the number of items in the target directory).

Next, we use shuf to generate a random number from our range:

shuf -i 0-"$(( ex_num_of_items - 1 ))" -n 1

  • "$(( ex_num_of_items - 1 ))" subtracts one from the number of items.
  • -i 0-"$(( ex_num_of_items - 1 ))" tells shuf to generate a random sorting of numbers from zero to the number of items (minus one).
  • -n 1 tells shuf to only output one number.

Randomly Selecting a Directory Item

One way to randomly select a directory item (with replacement) is to add each item returned from our find command to an indexed array. We can use declare and mapfile to achieve this:

declare -a ex_obj_paths
mapfile -t ex_obj_paths < \
    <(find ex_dir -mindepth 1 -maxdepth 1 ! -name '.*')

Above, we use process substitution and redirection to use the output of our find command to populate our ex_obj_paths indexed array.

We can use the random number we previously generated to select a random object from our array. The random number serves as an array item's index number.

Pulling It All Together

We have the pieces required to select random items from a directory, but it would be nice to pull things together into a command line program that we can run from our GNU/Linux desktop. The idea is to pass the program a directory path and have it output the paths of random directory items (it might be nice to see the associated chosen random numbers, too).

Once you find an interesting object, you can quit the program. After quitting, the last randomly selected item path is placed on the system clipboard, enabling you to pass it along to another program for perusal or consumption.

The following script accomplishes this:

It requires xclip to modify the system clipboard and has a -o (--open) option to automatically use xdg-open to open the last randomly selected item chosen before quitting the program.

Using the Shell to Create Custom Solutions

On GNU/Linux, there are often pre-made programs available that can accomplish the most esoteric of tasks. However, taking the time to use Bash to create your own solution can be a rewarding and edifying experience.

Enjoyed this post?

Subscribe to the feed for the latest updates.