package Util::FileList; ############################################################################## # # DESCRIPTION: This class allows you to do a number of useful things with # DESCRIPTION: a list of files. # DESCRIPTION: Sub-classes such as Util::FITSlist and Util::EventFileList # DESCRIPTION: add additional funtionality for specific types of files. # # HISTORY: # # VERSION: 1.0 # ############################################################################## use Util::Tool; use strict; my $INVOCATION; # incremented each time new is called keeps file names unique ############################################################################### # constructor ############################################################################### sub new { #(file1, file2, file3 ...) my $proto = shift; my $class = ref($proto) || $proto; my $self={}; @{$self->{FILES}}=@_; #################################################### # increment counter each time an object is created # so we can keep teporary file names unique #################################################### $INVOCATION++; $self->{TMP_FILE_SUFFIX}="_${INVOCATION}.tmp"; $self->{LIST_FILE}="file_list".$self->{TMP_FILE_SUFFIX}; ################################################### # maximum line length for in-lining the files in # an FTOOL parameter ################################################### $self->{MAX_PARAM_LENGTH}=80; bless($self,$class); return $self; } # end of constructor ################################## # ACCESSORS: ################################## ############################################################################ # append a file to the end of the list ############################################################################ sub add { my $self = shift; my $file = shift; push @{$self->{FILES}}, ($file); } # end of add method ################################################# # returns an array containing all the file names ################################################# sub files { my $self=shift; return (@{$self->{FILES}}); } ################################################# # returns the number of files in the list ################################################# sub count { my $self=shift; my $count = @{$self->{FILES}}; return $count; } ################################################### # returns the name of the index-th file in the list ################################################### sub file { my $self=shift; my $index=shift; if(! defined $index ) {$index=0} return ${$self->{FILES}}[$index]; } ########################################################################## # returns the names of all the files in a form suitable for # use in an FTOOL parameter. # See the "as_param" method. # Note this is the same as the "files" method # but it is separate to allow subclasses to override it ########################################################################## sub files_for_param { my $self=shift; return ($self->files()); } ########################################################################## # get or set the name of the unique suffix used for temporary file names ########################################################################## sub tmp_file_suffix { my $self=shift; if(@_) { $self->{TMP_FILE_SUFFIX}=shift} return $self->{TMP_FILE_SUFFIX}; } ############### # METHODS: ############### ############################################################################# ############################################################################# # Give the list of files in a form suitable for use as an input parameter # to an FTOOL. First tries to format the files as a space-separated # list. If the length of this string is longer than $self->{MAX_PARAM_LENGTH} # it dumps the file names to an ascii file and returns the name of that # file preceeded by "@". This is a standard FTOOL convention. # The temporary file is deleted when this object is destroyed, so # it will generally be necessary to explicitly call the DESTROY method # to force the list file to stick around long enough to be used. ############################################################################# sub as_param { my $self=shift; my $value=join ' ', $self->files_for_param(); if(length($value) <= $self->{MAX_PARAM_LENGTH} ) { ############################################### # file list is short enough to fit on one line ############################################### return $value; } else { ############################################## # too many files - we have to dump the list # to a temporary file ############################################## open LIST, ">$self->{LIST_FILE}"; print LIST join "\n", $self->files_for_param(); print LIST "\n"; # FTOOLS need this close LIST; return "\@$self->{LIST_FILE}"; } } # end of as_param method ############################################################################# ############################################################################# # merge all the files in the list into a single file # and return the name of the merged file. # If the list contains only one file this method does nothing and returns # the name of that one file. # This method simply concatenates the files. Subclasses override this method. ############################################################################# sub merge { my $self=shift; my $merged=shift; if(@{$self->{FILES}} == 1 ) { #################################################### # only one file so just give the name of that file #################################################### return $self->file(); } ################################## # concatenate the files ################################## unlink $merged; open MERGED, ">$merged"; my $file; foreach $file ($self->files()) { open IN, "<$file"; print MERGED <IN>; close IN; } close MERGED; ##################################### # return the name of the merged file ##################################### return $merged; } ############################################################################# ############################################################################# # create a new list which is a subset of this one. # The arguments are the index of the first and last files in the list. # The index of the first file is zero. # - If $to is beyond the end of the list, it is reduced to the end of the list # - If $from is beyond the end of the list or $from >$to, undef is returned. # - If $from==0 and $to is at or beyond the end of the list, a reference # to this same object is returned. ############################################################################# sub sublist { my $self=shift; my $from=shift; my $to=shift; my $nfiles=@{$self->{FILES}}; ######################################### # handle special cases ######################################### if($to >= $nfiles) {$to= $nfiles-1 } if($from >= $nfiles or $to<$from ) {return undef } if($from==0 && $to==$nfiles-1) {return $self} ######################################### # create and return a sub-list ######################################### return $self->new(@{$self->{FILES}}[$from..$to]); } # end of sublist method ############################################################################# ############################################################################# # delete all the files in the list. # If a log object and an message string are given, that message will be # logged if any files are removed. ############################################################################# sub delete { my $self=shift; my $log=shift; my $message=shift; my @files=$self->files(); if($log && $message && @files) { $log->entry($message); $log->text(join("\n", @files)) ; } foreach (@files ) { unlink; } } # end of delete method ############################################################################# ############################################################################# # make a tar file containing all the files in the list ############################################################################# sub tar { my $self=shift; my $tarfile=shift; Util::Tool->new("system","tar") ->command_line("-cvf $tarfile",$self->files() ) ->run(); return $self; } #end of tar method ############################################################################# ############################################################################# # destructor - deletes temporary file list. This method should probably be # called explicitly after using the as_param method ############################################################################# sub DESTROY { my $self=shift; unlink $self->{LIST_FILE}; } 1;