ken@titan ~/tmp/pm_11150231_dir_rand_select
$ ls -1R
.:
a.x
b.y
c.z
inc1
inc2
skip
./inc1:
g.w
h.x
i.y
j.z
./inc2:
k.u
l.v
m.w
n.x
o.y
p.z
./skip:
d.x
e.y
f.z
####
#!/usr/bin/env perl
use strict;
use warnings;
use autodie;
use File::Spec;
use List::Util 'shuffle';
# For production, you'd probably want to read the
# following values from options, config, etc.
my $dir = '/home/ken/tmp/pm_11150231_dir_rand_select';
my @includes = (qr{\.x$}, qr{\.z$});
my @excludes = (qr{skip$}, qr{inc2\/p\.z$});
my $list_length = 3;
my $re = {
inc => qr{(?:@{[join '|', @includes]})},
exc => qr{(?:@{[join '|', @excludes]})},
};
my @all_files;
get_files(\@all_files, $dir, $re);
my @playlist = (shuffle @all_files)[0 .. $list_length - 1];
print "$_\n" for sort @playlist;
sub get_files {
my ($collected, $dir, $re) = @_;
return if $dir =~ $re->{exc};
opendir(my $dh, $dir);
for my $file (grep ! /^(?:\.|\.\.)$/, readdir $dh) {
my $path = File::Spec::->catfile($dir, $file);
next if $path =~ $re->{exc};
if (-d $path) {
get_files($collected, $path, $re);
}
elsif (-f _) {
next unless $path =~ $re->{inc};
push @$collected, $path;
}
else {
# maybe handle other file types here
}
}
return;
}
####
$ ./rand_select_files.pl
/home/ken/tmp/pm_11150231_dir_rand_select/inc1/h.x
/home/ken/tmp/pm_11150231_dir_rand_select/inc1/j.z
/home/ken/tmp/pm_11150231_dir_rand_select/inc2/n.x
####
$ ./rand_select_files.pl
/home/ken/tmp/pm_11150231_dir_rand_select/a.x
/home/ken/tmp/pm_11150231_dir_rand_select/c.z
/home/ken/tmp/pm_11150231_dir_rand_select/inc1/j.z