Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Random File as parameter for a program

by sacked (Hermit)
on May 10, 2004 at 17:41 UTC ( [id://352158]=CUFP: print w/replies, xml ) Need Help??

Perl makes it easy to select a random file and pass it as an argument to another program. I use the following script every day to select random mp3 playlists for my xmms queue. Here are examples from the pod:
$ random_file.pl /path/to/mp3s -t mp3 -e 'xmms -e' # random song $ random_file.pl /path/to/mp3s -t m3u -e 'xmms -e' # random playlist $ random_file.pl /path/to/mp3s -d -e 'xmms -e' # random directory
One of the nice features of this program is that it caches recently selected entries, so you don't end up adding the same mp3s over and over again, for example.

You may run the program without any options for a brief overview of command line options, or run perldoc FILENAME for details.
Comments are most welcome.
#!/usr/local/bin/perl -w # # $Id: random_file.pl,v 1.17 2004/05/10 17:33:50 zackse Exp $ # # picks a random file or directory and passes it to another program use strict; use File::Find; use Cache::FileCache; use Getopt::Long; use Pod::Usage; my %opts; $opts{dirs}= shift; unless ( $opts{dirs} and -d $opts{dirs} ) { warn "need a directory\n\n"; pod2usage(2); } GetOptions( \%opts, 'type:s@', 'dironly', 'exec:s', 'ignore:s@', 'cache:s', 'hel +p' ); pod2usage(1) if $opts{help}; $opts{exec} ||= '/bin/echo'; # bleh pod2usage(2) unless $opts{exec}; ## my $files= get_candidates( $opts{dirs} ); my $selected= select_random_file( \%opts ); die "No match\n" unless $selected; exec( split( ' ' => $opts{exec} ), $selected ) or die "error running '$opts{exec} $selected': $!\n"; # should never get here exit; ## sub get_candidates { my $path= shift || return []; # stores all files in specied directory tree my $dircache= Cache::FileCache->new({ namespace => $path, default_expires_in => 86400, # 1 day auto_purge_interval => 3600 * 5, # 5 hours }); my $files= $dircache->get( $path ); # regenerate file list unless( $files and @$files ) { find( sub { push @$files => $File::Find::name }, $path ); $dircache->set( $opts{dirs} => $files ); } return $files; } sub select_random_file { my $opts= shift; my( $exts, $ignores )= map generate_patterns( $_ ) => @$opts{qw/type + ignore/}; # stores selected file my $cache= Cache::FileCache->new({ namespace => $opts->{cache} || 'random_file', default_expires_in => 86400 * 4, # 4 days auto_purge_interval => 3600 * 5, # 5 hours }); my $file_count; my $selected= ''; foreach( @$files ) { # match directories only? next if $opts->{dironly} and ! -d; # matches ignore list? next if $ignores && $_ =~ $ignores; # matches extensions list? next unless ( ! $exts || /(?:$exts)\z/o ); # already selected recently? next if $cache->get( $_ ); # OK, candidate for selection $selected= $_ if rand( ++$file_count ) < 1; # see perlfaq5 } return unless $selected; $cache->set( $selected => 1 ); return $selected; } sub generate_patterns { return map { my $pats= join '|' => map "\Q$_\E" => @{ $_ || [] }; $pats ? qr/$pats/ : undef } @_; } __END__ =head1 NAME random_file.pl - pick a random file in a directory, pass it as an argu +ment to another program =head1 SYNOPSIS random_file.pl B<PATH> -exec B<PROGRAM> [ -type B<FILEMASK> ] [ -ignore B<EXCLUSION> ] [ -c B<CACHE_NAME> ] [ -d ] Options: -c --cache NAMESPACE use NAMESPACE for cache -d --dironly only match against directories -e --exec PROGRAM pass selection as argument to PROGRAM -h --help display this help text -i --ignore PATTERN ignore files matching PATTERN -t --type EXTENSION files must match EXTENSION =head1 EXPLANATION Perhaps you have a large directory of mp3s, but you've grown tired of scanning through the file dialog from xmms. This program can select a random song, or playlist, or directory, and enqueue it for you: $ random_file.pl /path/to/mp3s -t mp3 -e 'xmms -e' # song $ random_file.pl /path/to/mp3s -t m3u -e 'xmms -e' # playlist $ random_file.pl /path/to/mp3s -d -e 'xmms -e' # directory Or maybe you have a nice collection of humorous videos you've download +ed from the Internet, and you'd like to view one at random with mplayer: $ random_file.pl /path/to/downloads -t mpg -t mpeg -e 'mplayer -idx +' =head1 OPTIONS =over 4 =item B<-cache> This option specifies the namespace for the cache used to save recentl +y selected items. The default is 'random_file'. =item B<-dironly> This option specifies that only directories should be matched. =item B<-exec> This is an external program to which the result will be passed as a parameter. =item B<-ignore> This is a pattern matching files you wish to be excluded from the gene +rated list of candidates. You may specify this option multiple times. =item B<-type> This is a pattern matching files you want to match, which is anchored +to the end of the filenames examined. For example, to match all mp3 files +, you would use C<-type mp3>. You may specify this option multiple times +. If you do not supply this parameter, all files will be matched. =back =head1 MORE EXAMPLES View a random image from the opera web browser's cache, ignoring any matching 'doubleclick': random_file.pl /home/zackse/.opera/cache4 -t jpe -i doubleclick \ -e /usr/bin/X11/xv =head1 USEFUL SHELL FUNCTIONS I use this program every day to add random entries to my xmms playlist +, and I have the following bash shell functions that make this easy: randalbum () { DIR=${1:-/usr/local/audio}; random_file.pl $DIR -t m3u -e 'xmms -e' } randmp3 () { DIR=${1:-/usr/local/audio}; random_file.pl $DIR -t mp3 -e 'xmms -e' } randmp3dir () { DIR=${1:-/usr/local/audio}; random_file.pl $DIR -d -e 'xmms -e' } You can supply an alternate directory as an argument to the function, or just update the default (/usr/local/audio) above. You may also find the following one-liner useful to dump the contents of the current cache of recently selected files (replace the cache nam +e 'random_file' as needed): $ perl -MCache::FileCache -le \ 'my $cache= Cache::FileCache->new({namespace, "random_file"}); print join "\n" => $cache->get_keys()' \ | sort =head1 AUTHOR Evan A. Zacks <e@zacks.org> Copyright (c) 2004 Evan A. Zacks. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO File::Find(3), Cache::Cache(3), perl(1) =cut

--sacked

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: CUFP [id://352158]
Approved by Popcorn Dave
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (2)
As of 2024-04-20 12:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found