List X random files from a directory
Try piping the ls
output to shuf
, e.g.
$ touch 1 2 3 4 5 6 7 8 9 0
$ ls | shuf -n 5
5
9
0
8
1
The -n
flag specifies how many random files you want.
Since you're mentioning zsh:
rand() REPLY=$RANDOM
print -rl -- *(o+rand[1,30])
You can replace print
with say ogg123
and *
with say **/*.ogg
It's quite easy to solve this with a tiny bit of Perl. Select four files at random from the current directory:
perl -MList::Util=shuffle -e 'print shuffle(`ls`)' | head -n 4
For production use though, I would go with an expanded script that doesn't rely on ls
output, can accept any dir, checks your args, etc. Note that the random selection itself is still only a couple of lines.
#!/usr/bin/perl
use strict;
use warnings;
use List::Util qw( shuffle );
if ( @ARGV < 2 ) {
die "$0 - List n random files from a directory\n"
. "Usage: perl $0 n dir\n";
}
my $n_random = shift;
my $dir_name = shift;
opendir(my $dh, $dir_name) || die "Can't open directory $dir_name: $!";
# Read in the filenames in the directory, skipping '.' and '..'
my @filenames = grep { !/^[.]{1,2}$/ } readdir($dh);
closedir $dh;
# Handle over-specified input
if ( $n_random > $#filenames ) {
print "WARNING: More values requested ($n_random) than available files ("
. @filenames . ") - truncating list\n";
$n_random = @filenames;
}
# Randomise, extract and print the chosen filenames
foreach my $selected ( (shuffle(@filenames))[0..$n_random-1] ) {
print "$selected\n";
}