Friday, May 31, 2013

In bash: pick a file at random out of a tree...and do something with it

This is a random one-liner (I cheated and used semicolons, so sue me) I came up with recently while desiring something random out of my random video collection to watch.

The ingredients to this one-liner are as follows:

nFiles=$(find ./ -name '*.avi' | wc -l)
The number of files to sample from.
chooseFile=$[$RANDOM*$nFiles/32767]
The line of output from which a file will be picked. $RANDOM is a bash variable that will always be a random number that ranges from 0 to 32767 each time it is referenced.
awk '{if (NR=='$chooseFile'){print $0;}}'
Pick a line of output and echo it.

Now, of course, to print this random file's path:

nFiles=$(find ./ -name '*.avi' | wc -l); chooseFile=$[$RANDOM*nFiles/32767]; find ./ -name '*.avi' | awk '{if (NR=='$chooseFile'){print $0;}}'

To use it as an argument is just one more simple step:

mplayer "$(nFiles=$(find ./ -name '*.avi' | wc -l); chooseFile=$[$RANDOM*nFiles/32767]; find ./ -name '*.avi' | awk '{if (NR=='$chooseFile'){print $0;}}')"

Wrapping in double-quotes allows the code inside of $( and ) (which gets executed, and its text entered right there in the command line) to evaluate while not letting any spaces or shell metacharacters that might lie in the printed path text get interpreted as marks that delineate shell arguments.