in reply to Add a fixed number of unique elements to hash

G'day Zsolt,

Your code uses a lot of older coding styles which I recommend you aim to move away from. These include: leading '&' on subroutine calls; use of package rather than lexical variables; and a lack of strict and warnings pragmata.

There are a number of ways to achieve what you want. In the code below, I've continued your use of opendir. The core File::Find module is popular, as are a number of related CPAN modules — I expect other monks may provide you with examples of those.

I've used fairly generic options for inclusions and exclusions — adapt to your needs.

I created this directory structure for testing (in the spoiler):

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

Here's the code:

#!/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; }

Here's a couple of sample runs:

$ ./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

— Ken