#!/usr/pkg/bin/perl
use File::Find;
sub printUse {
print "\nUSAGE:\n"
. "$0 (-r <DIR> || -f <DIR>)[-r <DIR> || -f <DIR>]* "
. "[-g <PAT> || -G <PAT>]*\n"
. "--Remember to use arguments in pairs.\n"
. " -f <DIR> picks from just the files in that directory and the"
. " other\n arguments.\n"
. " -r <DIR> picks from the files in that directory, its"
. " subdirectories,\n and the other arguments.\n"
. " -g <PAT> picks only from those that match this pattern and"
. " all other patterns.\n"
. " -G <PAT> same as -g but is case sensitive.\n"
. "--If the output is a blank line, your patterns aren't"
. " matching any files.\n\n";
}
### MAIN BIT ###
## This makes a big pick-list of all the files in -f <DIR>s and in -r <DIR>s
## as well as all the -r <DIR>s subdirectories. This list is filtered so
## that it contains only files matching any -g or -G options.
## For example, to match only files ending in jpg, jpeg, JPG and JPEG, use
## -g 'jpe?g$' [quote or escape the '$' from your shell]
if ($#ARGV % 2 == 0 || $#ARGV == -1) {
printUse;
print "ERROR: Incorrect number of arguments.\n\n";
exit(1);
}
# EXPLAIN the following bit;
# this makes two hashes, the first (%argrev) uses the argument as the key, and
# stores the meaning [ie "-r . -f .. -f /etc" becomes:
# ( '.' => '-r',
# '..' => '-f',
# '/etc' => '-f' ) ]
# the second (%arg) uses the meaning as the key, and stores the argument(s)
# in a list. [ie the above becomes:
# ( '-r' => ('.'),
# '-f' => ('..', '/etc') ) ]
my %argrev = reverse @ARGV;
my %arg;
foreach (keys %argrev) {
push(@{$arg{$argrev{$_}}}, $_);
}
##showing that it worked
#print "\%argrev:\n";
#print map { "$_ => " . $argrev{$_} . "\n" } keys %argrev; print "\n";
#print "\%arg:\n";
#print map { "$_ => (@{$arg{$_}})\n" } keys %arg; print "\n";
#exit(0);
# end EXPLAINed bit;
if (!exists $arg{'-r'} && !exists $arg{'-f'}) {
printUse;
print "ERROR: Did not have at least one -r or -f type\n\n";
exit(0);
}
{
my @badarg = grep { ($_ ne '-r' && $_ ne '-f' && $_ ne '-G' && $_ ne '-g') }
keys %arg;
my $counter = 0;
foreach (@badarg) {
$counter++;
}
if ($counter != 0) {
printUse;
print "\n";
foreach (@badarg) {
print "ERROR: We don't support the operation $_.\n";
}
exit(1);
}
}
my @picklist;
foreach (@{$arg{"-r"}}) {
push (
@picklist,
recurseDir( verifyDir( fixDir($_) ) )
);
}
foreach (@{$arg{"-f"}}) {
push (
@picklist,
getDir( verifyDir( fixDir($_) ) )
);
}
print pickFrom(@picklist);
print "\n";
### END MAIN BIT ###
sub filter {
#return true if we match the filters
#print "filter: $_[0]\n";
my $str = $_[0];
foreach (@{$arg{"-g"}}) { #case insensitive
if ($str !~ m/$_/i) {return 0;} #if false ret false
}
foreach (@{$arg{"-G"}}) { #case sensitive
if ($str !~ m/$_/) {return 0;} #if false ret false
}
return 1; #else true
}
sub fixDir {
#append a closing / if needed;
if ($_[0] =~ m/\/$/) {
return $_[0];
} else {
return $_[0] . "/";
}
}
sub verifyDir {
#check if the file is a directory
if (!-d $_[0])
{
printUse;
print "ERROR: \"$_[0]\" is not a directory.\n\n";
exit(1);
}
return $_[0];
}
sub pickFrom {
#pick a random out of the passed in list
return( $_[ rand @_] );
}
sub recurseDir {
#check a directory tree return all filenames with path.
my @ret;
find( sub { if (filter ($_)) {push(@ret, $File::Find::name);} },
$_[0]
);
return @ret;
}
sub getDir {
#check directory all filenames with path.
if (!opendir(DIR, $_[0])){
die "$_[0] is Not a directory!\n";
}
my @dir = readdir(DIR);
closedir(DIR);
@dir = grep {filter ($_)} @dir;
foreach(@dir){$_ =~ s/.*/$_[0]$&/;}
return @dir;
}