#!@DASPERL ! +-======-+ ! Copyright (c) 2003-2007 United States Government as represented by ! the Admistrator of the National Aeronautics and Space Administration. ! All Rights Reserved. ! ! THIS OPEN SOURCE AGREEMENT ("AGREEMENT") DEFINES THE RIGHTS OF USE, ! REPRODUCTION, DISTRIBUTION, MODIFICATION AND REDISTRIBUTION OF CERTAIN ! COMPUTER SOFTWARE ORIGINALLY RELEASED BY THE UNITED STATES GOVERNMENT AS ! REPRESENTED BY THE GOVERNMENT AGENCY LISTED BELOW ("GOVERNMENT AGENCY"). ! THE UNITED STATES GOVERNMENT, AS REPRESENTED BY GOVERNMENT AGENCY, IS AN ! INTENDED THIRD-PARTY BENEFICIARY OF ALL SUBSEQUENT DISTRIBUTIONS OR ! REDISTRIBUTIONS OF THE SUBJECT SOFTWARE. ANYONE WHO USES, REPRODUCES, ! DISTRIBUTES, MODIFIES OR REDISTRIBUTES THE SUBJECT SOFTWARE, AS DEFINED ! HEREIN, OR ANY PART THEREOF, IS, BY THAT ACTION, ACCEPTING IN FULL THE ! RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN THIS AGREEMENT. ! ! Government Agency: National Aeronautics and Space Administration ! Government Agency Original Software Designation: GSC-15354-1 ! Government Agency Original Software Title: GEOS-5 GCM Modeling Software ! User Registration Requested. Please Visit http://opensource.gsfc.nasa.gov ! Government Agency Point of Contact for Original Software: ! Dale Hithon, SRA Assistant, (301) 286-2691 ! ! +-======-+ # bacon is a utility for performing tasks on a list of files use FindBin; # find location of the this script use lib "$FindBin::Bin"; # make perl libraries available use Env; # make env vars readily available use File::Basename; # for basename(), dirname() use File::Find; # for using Find command use Getopt::Long; # command line options #use File::Copy; # for copy() #use Time::Local; # time functions #use Shell qw(rcp rsh scp ssh); # make C-shell commands available @line_list = (); print "---------------------------------------------------------------------------------\n" if ($v) ; initialize(); @ttl_lines_constructed = read_rc(); print "--- ttl_lines_constructed = @ttl_lines_constructed \n" if ($v); run_lines(@ttl_lines_constructed); exit (0); sub initialize() { $increment = 0; $time_steps = 0; # set default options # ------------------- $opt_1 = 0; $opt_d = "./"; $opt_h = 0; $opt_rc = "bacon.rc"; $opt_v = 0; $remote_shell = 'rsh'; $exit_code = 0; # command line options # -------------------- my $rc= GetOptions( "1", "d=s", "h", "rc=s", "v"); print "rc = $rc \n"; manpage() if ( $opt_h || $#ARGV <0 || $ARGV[0] eq 'help' || !$rc ); $nofork = $opt_1; $work_dir = $opt_d; $rc_file_use = $opt_rc; $v = $opt_v; # check for conflicting option settings ## ## if (dirname($0) ne "" ) { if ($opt_rc eq "bacon.rc" ) { $rc_file_use = dirname ($0) . "/" . $rc_file_use; } } $work_dir = "$work_dir\/"; print "THE FOLLOWING OPTIONS HAS BEEN SET \n"; print "================================== \n"; print "nofork = $nofork \n"; print "verbose = $v \n"; print "work_dir = $work_dir \n"; print "rc_file_use = $rc_file_use \n"; print "================================== \n"; #if ($work_dir ne './' ) {chdir $work_dir; print "Directory changed to $work_dir\n";} $pwd = `pwd`; print "current directory = $pwd \n"; } sub read_rc { # get list of files from rc file print "Read Resource File..." if ($v); my @ttl_lines_constructed = (); my @line_list_temp = (); my $temp = ""; unless ( open( RCFILE, $rc_file_use ) ) { print "(acquire) ERROR: Configuration file '", $rc_file_use, "' can not be opened.\n"; exit (1); } while ( ) { chop; if ((! /^#/ )&&(/.{1,}/)) { #chomp( $line = $_ ); push (@line_list_temp, "$_\n"); my @lines_constructed = ""; my $first_string = ""; my $expanded_first_string = ""; $line = $_; #$line1 = quotemeta($line); print "\n" if ($v); print "\n" if ($v); print "\n" if ($v); print "---------------B E G I N---------------\n" if ($v); print " line = $line \n" if ($v); @temp_line = (); @temp_line = split(" ", $line, 99999); print " >>> temp_line = @temp_line \n" if ($v); $first_string = shift @temp_line; print " process_rc : first_string = $first_string \n" if ($v) ; $expanded_first_string = expand_searchstring($first_string); print " process_rc : expanded first_string = $expanded_first_string \n" if ($v); $first_string = quotemeta ($first_string); print " quotemeta process_rc : first_string = $first_string \n" if ($v); my @lines_constructed = ""; @lines_constructed = construct_lines($expanded_first_string, $first_string, @temp_line); print "\n" if ($v); print " >>> lines_constructed = \n" if ($v); print "@lines_constructed\n" if ($v); print "----------------E N D -----------------\n" if ($v); foreach $temp (@lines_constructed) { push (@ttl_lines_constructed , "$temp END_OF_A_RECORD"); } # push (@ttl_lines_constructed , "END_OF_RECORD"); } } close( RCFILE ); print "Resource File Read" if ($v); return (@ttl_lines_constructed); } sub expand_searchstring { my ( $file ) = @_; #my ( $yyyy,$yy,$mm,$dd,$hh,$file ) = @_; ($file = $file) =~ s/%y4/[0-9][0-9][0-9][0-9]/g; ($file = $file) =~ s/%y2/[0-9][0-9]/g; ($file = $file) =~ s/%m3/[A-Za-z][A-Za-z][A-Za-z]/g; ($file = $file) =~ s/%m2/[0-1][0-9]/g; ($file = $file) =~ s/%d2/[0-3][0-9]/g; ($file = $file) =~ s/%h2/[0-2][0-9]/g; ($file = $file) =~ s/%s/^\.(.*?)/g; #($file = $file) =~ s/%n/[^A-Za-z]/g; return $file; } sub construct_lines { my ($expanded_first_string, $first_string, @temp_line) = @_; my @lines_constructed = ""; my $single_line = ""; print " construct_lines - \n" if ($v); print " construct_lines - expanded_first_string = $expanded_first_string\n" if ($v); print " construct_lines - first_string = $first_string\n" if ($v); print " construct_lines - temp_line = @temp_line\n" if ($v); chdir ($work_dir); find sub { $filename_temp = basename ($File::Find::name); if ($v) {print " --- Found ---> $filename_temp \n" if (/$expanded_first_string/); } if (/$expanded_first_string/) { @temp_line_NOT = (); $single_line = construct_single($filename_temp, $first_string, @temp_line); print " construct_lines : single_line = $single_line \n" if ($v); push (@lines_constructed, $single_line); } }, '.'; chdir($pwd); return (@lines_constructed); } sub construct_single { my ($filename_temp, $first_string, @temp_line ) = @_; my $construct_final_line = ""; my $second_string = ""; print " construct_single - \n" if ($v); print " construct_single - temp_line = @temp_line\n" if ($v); print " construct_single - filename_temp = $filename_temp\n" if ($v); print " construct_single - first_string = $first_string\n" if ($v); foreach $temp_element (@temp_line) { print " construct_single: temp_element = $temp_element <------------- \n" if ($v); if ($temp_element =~ /\%s(.*)/) { print " construct_single : string found --- calling construct_2ndstring \n" if ($v); $second_string = construct_2ndstring($first_string, $filename_temp, $temp_element); $construct_final_line = "$construct_final_line $work_dir$second_string"; } elsif ($temp_element =~ /\%file/) { $construct_final_line = "$construct_final_line $work_dir$filename_temp"; } else { $construct_final_line = "$construct_final_line $temp_element"; } } $construct_final_line = "$construct_final_line\n"; return ($construct_final_line); } sub call_pasta { my ($filename_temp, $first_string) = @_; my $y4 = $y2 = $m2 = $m3 = $d2 = $h2 = $s = $h = ""; $first_string =~ s/\\//g; $filename_temp = basename ($filename_temp); print " call_pasta \n" if ($v); print " call_pasta filename_temp = $filename_temp \n" if ($v); print " call_pasta first_string = $first_string \n" if ($v); #$results = system ("home/jyoon/yoon/bacon/pasta $filename_temp $first_string"); #$results = system("/home/jyoon/yoon/bacon/pasta"); $results = `/home/jyoon/yoon/bacon/pasta $filename_temp $first_string`; print " call_pasta results = $results \n" if ($v); ($y4, $y2, $m2, $m3, $d2, $h2, $s, $h) = split (" " , $results); # ($y4, $y2, $m2, $m3, $d2, $h2, $s) = system("pasta $filename_temp $first_string"); print " call_pasta results = $y4, $y2, $m2, $m3, $d2, $h2, $s \n" if ($v); return ($y4, $y2, $m2, $m3, $d2, $h2, $s); } sub construct_2ndstring { my ($first_string, $filename_temp, $temp_element) = @_; my $y4 = $y2 = $m2 = $m3 = $d2 = $h2 = $s = ""; print " inside of construct_2ndstring \n" if ($v); print " inside of construct_2ndstring first_string = $first_string\n" if ($v); print " inside of construct_2ndstring filename_temp = $filename_temp\n" if ($v); print " inside of construct_2ndstring before temp_element = $temp_element\n" if ($v); # ($y4, $y2, $m2, $m3, $d2, $h2, $s) = call_pasta($filename_temp, $first_string); ($y4, $y2, $m2, $m3, $d2, $h2, $s) = pasta_replacement($filename_temp, $first_string); $temp_element =~ s/%y4/$y4/g; $temp_element =~ s/%y2/$y2/g; $temp_element =~ s/%m3/$m3/g; $temp_element =~ s/%m2/$m2/g; $temp_element =~ s/%d2/$d2/g; $temp_element =~ s/%h2/$h2/g; $temp_element =~ s/%s/$s/g; print " inside of construct_2ndstring after temp_element = $temp_element\n" if ($v); return ($temp_element); } sub run_lines { my (@lines_to_run ) = @_; $lines_scaler = join (" ", @lines_to_run); @lines_array = split ("END_OF_A_RECORD", $lines_scaler); # test system call #push (@lines_array , "ls -glas "); foreach $lines_single (@lines_array) { chomp ($lines_single); if ($lines_single =~ /\w+/) { print "\n"; if ($lines_single =~ /\&/ && ! $nofork ) { print " >>>- BACKGROUND LAUNCH --> $lines_single\n"; } else { print " >>>- Launching ---> $lines_single\n " ; } $exit_status = system ("$lines_single"); if ($exit_status) { print " !!! exit_status = $exit_status \n"; } else { print " - SUCCESSFUL -> $lines_single \n"; } print "\n" if ($v); } } A } sub pasta_replacement { # Same function as Pasta.c # but written in perl. my ($filename_temp, $first_string) = @_; print "first_string = $first_string \n filename_temp = $filename_temp\n" if ($v); $y4 = "yyyy"; $y2 = "YY"; $m2 = "mm"; $m3 = "MMM"; $d2 = "DD"; $h2 = "HH"; $s = ""; $first_string =~ s/\\//g; $filename_temp = basename ($filename_temp); $first_string =~ s/%y4/yyyy/g; $first_string =~ s/%y2/YY/g; $first_string =~ s/%m3/MMM/g; $first_string =~ s/%m2/mm/g; $first_string =~ s/%d2/DD/g; $first_string =~ s/%h2/HH/g; $string_index = index ($first_string, "%s"); $period_index = index ($filename_temp, ".", $string_index); $string_length = $period_index - $string_index; $s = substr ($filename_temp, $string_index, $string_length); $first_string =~ s/%s/$s/g; if ($first_string =~ /yyyy/) { $index_temp = index($first_string, "yyyy"); $y4 = substr ($filename_temp, $index_temp, 4); } if ($first_string =~ /YY/ ) { $index_temp = index($first_string, "YY" ); $y2 = substr ($filename_temp , $index_temp, 2); } if ($first_striong =~ /MMM/ ) { $index_temp = index($first_string, "MMM" ); $m3 = substr ($filename_temp, $index_temp, 3); } if ($first_string =~ /mm/ ) { $index_temp = index($first_string, "mm" ); $m2 = substr ($filename_temp, $index_temp, 2); } if ($first_string =~ /DD/) { $index_temp = index($first_string, "DD" ); $d2 = substr ($filename_temp, $index_temp, 2); } if ($first_string =~ /HH/) { $index_temp = index($first_string, "HH" ); $h2 = substr ($filename_temp, $index_temp, 2); } print " pasta results = $y4, $y2, $m2, $m3, $d2, $h2, $s \n" if ($v); #print " pasta results = $y4, $y2, $m2, $m3, $d2, $h2, $s \n" ; return ($y4, $y2, $m2, $m3, $d2, $h2, $s); } #...................................................................... sub manpage { print<<"EOF1"; NAME bacon - (Ba)tch File (Con)verter SYNOPSIS bacon [...options...] DESCRIPTION Bacon is a general purpose utility for launching batch jobs using a list of file templates specified in the resource file (see RESOURCE FILE below). It performs tasks on a list of files specified by means of GrADS like templates. For example, a resource file could specify a file name of the form: %s.bkg.eta.%y4%m2%d2.nc4 dyn2prs.x -o %s.ana.prs.%y4%m2%d2.nc4 %file OPTIONS -1 single processor mode (no forks) . This mode overrides the "&" (ampersand) option set in the resource files and forces Bacon to wait for completion of each executable listed in the resource file before moving on to next executable. -d path working (local) directory (default: ./) -rc fname resource file name (default: bacon.rc) -v verbose mode (default is real quiet) -h help, prints this page RESOURCE FILES Bacon resource files ( bacon.rc) consist of comment lines starting with '#' or a file name templates of the form filetemplate executable [ options ] [ filetemplate2,3,4 ] file [ & ] SHORT EXPLANATION : First, Bacon finds all files that match the first file template Second, the GrADS like patterns are extracted and second, third, or fourth set of "file templates" is expanded. Third, the "executable" is launched. For example, a typical line in the bacon.rc file would be: %s.bkg.eta.%y4%m2%d2.nc4 dyn2prs.x -o %s.ana.prs.%y4%m2%d2.nc4 %file & %s.bkg.eta.%y4%m2%d2.nc4 coards2grib %file In this example, the filename "template" is a GrADS like pattern for matching file names. Supported tokens are: %y4 year, e.g., 1997 %y2 year, e.g., 97 %m2 month, e.g., 12 %d2 day, e.g., 31 %h2 hour, e.g., 18 %s any string, e.q., v016a_b55 In addition to GrADS-like tokens, any defined environment variable can be used in the file name template. ------------------------------------------ DETAILED EXPLANATION OF ABOVE EXAMPLE: ------------------------------------------ First, the first file-template (%s.bkg.eta.%y4%m2%d2.nc4) is used to find all files that match the template. Lets assume it found the following 3 files: v016a_b55.bkg.eta.19971231.nc4 vaaaa_v12.bkg.eta.19981131.nc4 vffff_a11.bkg.eta.19990128.nc4 From here, Bacon utilizes the same logic found in Pasta.pl to extract the GrADS like patterns such as %y4, %m2, %d2, %s... These matched values are pluged into the second file-template if found, %s.ana.prs.%y4%m2%d2.nc4 and expanded to produce : v016a_b55.ana.prs.19971231.nc4 Same is done with the remaining files found above, vaaaa_v12.bkg.eta.19981131.nc4 vffff_a11.bkg.eta.19990128.nc4 As a result, bacon will have the following lines queued for launch. dyn2prs.x -o v016a_b55.bkg.eta.19971231.nc4 v016a_b55.ana.prs.19971231.nc4 & dyn2prs.x -o vaaaa_v12.bkg.eta.19981131.nc4 vaaaa_v12.ana.prs.19981131.nc4 & dyn2prs.x -o vffff_a11.bkg.eta.19990128.nc4 vffff_a11.ana.prs.19990128.nc4 & ----------------- RC file Options ----------------- & (ampersand ) - if an ampersand is attached at the end of a line in a resource file, that particular executable will be launched in the background. Example: %s.bkg.eta.%y4%m2%d2.nc4 dyn2prs.x -o %s.ana.prs.%y4%m2%d2.nc4 %file & In this case, dyn2prs.x and it's arguments will be executed with the & (ampersand) attached. This is useful if you don't want to wait around for one job to finish. -------------------------------------------------------------------------------------- SEE ALSO acquire - data acquisition utility pesto - (P)ut (E)xperiments in Mass (Sto)rage pasta - Utility that returns experiment id, year, month, day, hour given a file name and a GrADS-like template AUTHORS Joon Yoon (jyoon\@dao.gsfc.nasa.gov) Arlindo da Silva (dasilva\@dao.gsfc.nasa.gov) EOF1 exit(1) }