8 use base
qw(Bio::Root::Root);
10 # as of 2016, worked on most systems, but will test this in a RC
11 my %modes = ( 0 => 'r', 1 => 'w', 2 => 'rw' );
15 # Use stream I/O in your module
16 $self->{'io'} = Bio::Root::IO->new(-file => "myfile");
17 $self->{'io'}->_print("some stuff");
18 my $line = $self->{'io'}->_readline();
19 $self->{'io'}->_pushback($line);
20 $self->{'io'}->close();
22 # obtain platform-compatible filenames
23 $path = Bio::Root::IO->catfile($dir, $subdir, $filename);
24 # obtain a temporary file (created in $TEMPDIR)
25 ($handle) = $io->tempfile();
29 This module provides methods that will usually be needed for any sort
30 of file- or stream-related input/output, e.g., keeping track of a file
31 handle, transient printing and reading from the file handle, a close
32 method, automatically closing the handle on garbage collection, etc.
34 To use this for your own code you will either want to inherit from
35 this module, or instantiate an object for every file or stream you are
36 dealing with. In the first case this module will most likely not be
37 the first class off which your class inherits; therefore you need to
38 call _initialize_io() with the named parameters in order to set file
39 handle, open file, etc automatically.
41 Most methods start with an underscore, indicating they are private. In
42 OO speak, they are not private but protected, that is, use them in
43 your module code, but a client code of your module will usually not
44 want to call them (except those not starting with an underscore).
46 In addition this module contains a couple of convenience methods for
47 cross-platform safe tempfile creation and similar tasks. There are
48 some CPAN modules related that may not be available on all
49 platforms. At present, File::Spec and File::Temp are attempted. This
50 module defines $PATHSEP, $TEMPDIR, and $ROOTDIR, which will always be set,
51 and $OPENFLAGS, which will be set if either of File::Spec or File::Temp fails.
53 The -noclose boolean (accessed via the noclose method) prevents a
54 filehandle from being closed when the IO object is cleaned up. This
55 is special behavior when a object like a parser might share a
56 filehandle with an object like an indexer where it is not proper to
57 close the filehandle as it will continue to be reused until the end of the
58 stream is reached. In general you won't want to play with this flag.
60 =head1 AUTHOR Hilmar Lapp
64 our ($FILESPECLOADED, $FILETEMPLOADED,
65 $FILEPATHLOADED, $TEMPDIR,
80 # try to load those modules that may cause trouble on some systems
86 print STDERR
"Cannot load File::Path: $@" if( $VERBOSE > 0 );
90 # If on Win32, attempt to find Win32 package
98 # Try to provide a path separator. Why doesn't File::Spec export this,
100 if ($^O
=~ /mswin/i) {
102 } elsif($^O
=~ /macos/i) {
110 $TEMPDIR = File
::Spec
->tmpdir();
111 $ROOTDIR = File
::Spec
->rootdir();
112 require File
::Temp
; # tempfile creation
116 if(! defined($TEMPDIR)) { # File::Spec failed
118 if (defined $ENV{'TEMPDIR'} && -d
$ENV{'TEMPDIR'} ) {
119 $TEMPDIR = $ENV{'TEMPDIR'};
120 } elsif( defined $ENV{'TMPDIR'} && -d
$ENV{'TMPDIR'} ) {
121 $TEMPDIR = $ENV{'TMPDIR'};
123 if($^O
=~ /mswin/i) {
124 $TEMPDIR = 'C:\TEMP' unless $TEMPDIR;
126 } elsif($^O
=~ /macos/i) {
127 $TEMPDIR = "" unless $TEMPDIR; # what is a reasonable default on Macs?
128 $ROOTDIR = ""; # what is reasonable??
130 $TEMPDIR = "/tmp" unless $TEMPDIR;
133 if (!( -d
$TEMPDIR && -w
$TEMPDIR )) {
134 $TEMPDIR = '.'; # last resort
137 # File::Temp failed (alone, or File::Spec already failed)
138 # determine open flags for tempfile creation using Fcntl
139 $OPENFLAGS = O_CREAT
| O_EXCL
| O_RDWR
;
140 for my $oflag (qw
/FOLLOW BINARY LARGEFILE EXLOCK NOINHERIT TEMPORARY/){
141 my ($bit, $func) = (0, "Fcntl::O_" . $oflag);
143 $OPENFLAGS |= $bit if eval { $bit = &$func(); 1 };
146 $ONMAC = "\015" eq "\n";
153 Usage : my $io = Bio::Root::IO->new( -file => 'data.txt' );
154 Function: Create new class instance. It automatically calls C<_initialize_io>.
155 Args : Same named parameters as C<_initialize_io>.
156 Returns : A Bio::Root::IO object
161 my ($caller, @args) = @_;
162 my $self = $caller->SUPER::new
(@args);
163 $self->_initialize_io(@args);
168 =head2 _initialize_io
170 Title : _initialize_io
171 Usage : $io->_initialize_io(@params);
172 Function: Initializes filehandle and other properties from the parameters.
173 Args : The following named parameters are currently recognized:
174 -file name of file to read or write to
175 -fh file handle to read or write to (mutually exclusive
176 with -file and -string)
177 -input name of file, or filehandle (GLOB or IO::Handle object)
179 -string string to read from (will be converted to filehandle)
180 -url name of URL to open
181 -flush boolean flag to autoflush after each write
182 -noclose boolean flag, when set to true will not close a
183 filehandle (must explicitly call close($io->_fh)
184 -retries number of times to try a web fetch before failure
185 -ua_parms when using -url, hashref of key => value parameters
186 to pass to LWP::UserAgent->new(). A useful value might
187 be, for example, {timeout => 60 } (ua defaults to 180s)
193 my($self, @args) = @_;
195 $self->_register_for_cleanup(\
&_io_cleanup
);
197 my ($input, $noclose, $file, $fh, $string,
198 $flush, $url, $retries, $ua_parms) =
199 $self->_rearrange([qw(INPUT NOCLOSE FILE FH STRING FLUSH URL RETRIES UA_PARMS)],
207 require LWP
::UserAgent
;
208 my $ua = LWP
::UserAgent
->new(%$ua_parms);
210 my ($handle, $tempfile) = $self->tempfile();
211 CORE
::close($handle);
213 for (my $try = 1 ; $try <= $retries ; $try++) {
214 $http_result = $ua->get($url, ':content_file' => $tempfile);
215 $self->warn("[$try/$retries] tried to fetch $url, but server ".
216 "threw ". $http_result->code . ". retrying...")
217 if !$http_result->is_success;
218 last if $http_result->is_success;
220 $self->throw("Failed to fetch $url, server threw ".$http_result->code)
221 if !$http_result->is_success;
227 delete $self->{'_readbuffer'};
228 delete $self->{'_filehandle'};
229 $self->noclose( $noclose) if defined $noclose;
230 # determine whether the input is a file(name) or a stream
232 if (ref(\
$input) eq 'SCALAR') {
233 # we assume that a scalar is a filename
234 if ($file && ($file ne $input)) {
235 $self->throw("Input file given twice: '$file' and '$input' disagree");
238 } elsif (ref($input) &&
239 ((ref($input) eq 'GLOB') || $input->isa('IO::Handle'))) {
243 # let's be strict for now
244 $self->throw("Unable to determine type of input $input: ".
245 "not string and not GLOB");
249 if (defined($file) && defined($fh)) {
250 $self->throw("Providing both a file and a filehandle for reading - ".
255 if (defined($file) || defined($fh)) {
256 $self->throw("File or filehandle provided with -string, ".
257 "please unset if you are using -string as a file");
259 open $fh, '<', \
$string or $self->throw("Could not read string: $!");
262 if (defined($file) && ($file ne '')) {
264 ($mode, $file) = $self->cleanfile;
266 my $action = ($mode =~ m/>/) ?
'write' : 'read';
267 $fh = Symbol
::gensym
();
268 open $fh, $mode, $file or $self->throw("Could not $action file '$file': $!");
272 # check filehandle to ensure it's one of:
273 # a GLOB reference, as in: open(my $fh, "myfile");
274 # an IO::Handle or IO::String object
275 # the UNIVERSAL::can added to fix Bug2863
276 unless ( ( ref $fh and ( ref $fh eq 'GLOB' ) )
277 or ( ref $fh and ( UNIVERSAL
::can
( $fh, 'can' ) )
278 and ( $fh->isa('IO::Handle')
279 or $fh->isa('IO::String') ) )
281 $self->throw("Object $fh does not appear to be a file handle");
284 binmode $fh, ':raw:eol(LF-Native)';
286 $self->_fh($fh); # if $fh not provided, defaults to STDIN and STDOUT
289 $self->_flush_on_write(defined $flush ?
$flush : 1);
298 Usage : $io->_fh($newval);
299 Function: Get or set the file handle for the stream encapsulated.
300 Args : Optional filehandle to use
301 Returns : Filehandle for the stream
306 my ($self, $value) = @_;
307 if ( defined $value) {
308 $self->{'_filehandle'} = $value;
310 return $self->{'_filehandle'};
318 $io->mode(-force => 1);
319 Function: Determine if the object was opened for reading or writing
320 Args : -force: Boolean. Once mode() has been called, the mode is cached for
321 further calls to mode(). Use this argument to override this
322 behavior and re-check the object's mode.
323 Returns : Mode of the object:
326 'rw' for readable and writable
327 '?' if mode could not be determined (e.g. for a -url)
332 my ($self, %arg) = @_;
334 # Method 1: IO::Handle::fdopen
335 # my $iotest = new IO::Handle;
336 # $iotest->fdopen( dup(fileno($fh)) , 'r' );
337 # if ($iotest->error == 0) { ... }
338 # It did not actually seem to work under any platform, since there would no
339 # error if the filehandle had been opened writable only. It could not be
340 # hacked around when dealing with unseekable (piped) filehandles.
342 # Method 2: readline, a.k.a. the <> operator
345 # if (defined $line) {
346 # $self->{'_mode'} = 'r';
348 # It did not work well either because <> returns undef, i.e. querying the
349 # mode() after having read an entire file returned 'w'.
351 if ( $arg{-force
} || not exists $self->{'_mode'} ) {
352 # Determine stream mode
356 # use fcntl if not Windows-based
357 if ($^O
!~ /MSWin32/) {
358 my $m = fcntl($fh, F_GETFL
, 0);
359 $mode = exists $modes{$m & 3} ?
$modes{$m & 3} : '?';
361 # Determine read/write status of filehandle
363 if ( defined( read $fh, my $content, 0 ) ) {
364 # Successfully read 0 bytes
367 if ( defined( syswrite $fh, '') ) {
368 # Successfully wrote 0 bytes
374 # Stream does not have a filehandle... cannot determine mode
377 # Save mode for future use
378 $self->{'_mode'} = $mode;
380 return $self->{'_mode'};
387 Usage : $io->file('>'.$file);
388 my $file = $io->file;
389 Function: Get or set the name of the file to read or write.
390 Args : Optional file name (including its mode, e.g. '<' for reading or '>'
392 Returns : A string representing the filename and its mode.
397 my ($self, $value) = @_;
398 if ( defined $value) {
399 $self->{'_file'} = $value;
401 return $self->{'_file'};
408 Usage : my ($mode, $file) = $io->cleanfile;
409 Function: Get the name of the file to read or write, stripped of its mode
410 ('>', '<', '+>', '>>', etc).
412 Returns : In array context, an array of the mode and the clean filename.
418 return ($self->{'_file'} =~ m/^ (\+?[><]{1,2})?\s*(.*) $/x);
425 Usage : $io->format($newval)
426 Function: Get the format of a Bio::Root::IO sequence file or filehandle. Every
427 object inheriting Bio::Root::IO is guaranteed to have a format.
429 Returns : Format of the file or filehandle, e.g. fasta, fastq, genbank, embl.
435 my $format = (split '::', ref($self))[-1];
443 Usage : $io->format($newval)
444 Function: Get the variant of a Bio::Root::IO sequence file or filehandle.
445 The format variant depends on the specific format used. Note that
446 not all formats have variants. Also, the Bio::Root::IO-implementing
447 modules that require access to variants need to define a global hash
448 that has the allowed variants as its keys.
450 Returns : Variant of the file or filehandle, e.g. sanger, solexa or illumina for
451 the fastq format, or undef for formats that do not have variants.
456 my ($self, $variant) = @_;
457 if (defined $variant) {
458 $variant = lc $variant;
459 my $var_name = '%'.ref($self).'::variant';
460 my %ok_variants = eval $var_name; # e.g. %Bio::Assembly::IO::ace::variant
461 if (scalar keys %ok_variants == 0) {
462 $self->throw("Could not validate variant because global variant ".
463 "$var_name was not set or was empty\n");
465 if (not exists $ok_variants{$variant}) {
466 $self->throw("$variant is not a valid variant of the " .
467 $self->format . ' format');
469 $self->{variant
} = $variant;
471 return $self->{variant
};
478 Usage : $io->_print(@lines)
479 Function: Print lines of text to the IO stream object.
480 Args : List of strings to print
481 Returns : True on success, undef on failure
487 my $fh = $self->_fh() || \
*STDOUT
;
488 my $ret = print $fh @_;
496 Usage : $io->_insert($string,1)
497 Function: Insert some text in a file at the given line number (1-based).
498 Args : * string to write in file
499 * line number to insert the string at
505 my ($self, $string, $line_num) = @_;
508 $self->throw("Could not insert text at line $line_num: the minimum ".
509 "line number possible is 1.");
512 my ($mode, $file) = $self->cleanfile;
513 if (not defined $file) {
514 $self->throw('Could not insert a line: IO object was initialized with '.
515 'something else than a file.');
517 # Everything that needs to be written is written before we read it
520 # Edit the file line by line (no slurping)
524 while (-e
"$file.$number.temp") {
527 $temp_file = "$file.$number.temp";
528 copy
($file, $temp_file);
529 open my $fh1, '<', $temp_file or $self->throw("Could not read temporary file '$temp_file': $!");
530 open my $fh2, '>', $file or $self->throw("Could not write file '$file': $!");
531 while (my $line = <$fh1>) {
532 if ($. == $line_num) { # right line for new data
533 print $fh2 $string . $line;
541 unlink $temp_file or $self->throw("Could not delete temporary file '$temp_file': $!");
543 # Line number check (again)
544 if ( $. > 0 && $line_num > $. ) {
545 $self->throw("Could not insert text at line $line_num: there are only ".
546 "$. lines in file '$file'");
548 # Re-open the file in append mode to be ready to add text at the end of it
549 # when the next _print() statement comes
550 open my $new_fh, '>>', $file or $self->throw("Could not append to file '$file': $!");
552 # If file is empty and we're inserting at line 1, simply append text to file
553 if ( $. == 0 && $line_num == 1 ) {
554 $self->_print($string);
563 Usage : local $Bio::Root::IO::HAS_EOL = 1;
564 my $io = Bio::Root::IO->new(-file => 'data.txt');
565 my $line = $io->_readline();
567 Function: Read a line of input and normalize all end of line characters.
569 End of line characters are typically "\n" on Linux platforms, "\r\n"
570 on Windows and "\r" on older Mac OS. By default, the _readline()
571 method uses the value of $/, Perl's input record separator, to
572 detect the end of each line. This means that you will not get the
573 expected lines if your input has Mac-formatted end of line characters.
574 Also, note that the current implementation does not handle pushed
575 back input correctly unless the pushed back input ends with the
576 value of $/. For each line parsed, its line ending, e.g. "\r\n" is
577 converted to "\n", unless you provide the -raw argument.
579 Altogether it is easier to let the PerlIO::eol module automatically
580 detect the proper end of line character and normalize it to "\n". Do
581 so by setting $Bio::Root::IO::HAS_EOL to 1.
583 Args : -raw : Avoid converting end of line characters to "\n" This option
584 has no effect when using $Bio::Root::IO::HAS_EOL = 1.
585 Returns : Line of input, or undef when there is nothing to read anymore
590 my ($self, %param) = @_;
591 my $fh = $self->_fh or return;
594 # if the buffer been filled by _pushback then return the buffer
595 # contents, rather than read from the filehandle
596 if( @
{$self->{'_readbuffer'} || [] } ) {
597 $line = shift @
{$self->{'_readbuffer'}};
602 # Note: In Windows the "-raw" parameter has no effect, because Perl already discards
603 # the '\r' from the line when reading in text mode from the filehandle
604 # ($line = <$fh>), and put it back automatically when printing
605 if( !$HAS_EOL && !$param{-raw
} && (defined $line) ) {
606 # don't strip line endings if -raw or $HAS_EOL is specified
607 $line =~ s/\015\012/\012/g; # Change all CR/LF pairs to LF
608 $line =~ tr/\015/\n/ unless $ONMAC; # Change all single CRs to NEWLINE
617 Usage : $io->_pushback($newvalue)
618 Function: Puts a line previously read with _readline back into a buffer.
619 buffer can hold as many lines as system memory permits.
621 Note that this is only supported for pushing back data ending with
622 the current, localized value of $/. Using this method to push
623 modified data back onto the buffer stack is not supported; see bug
631 # fix for bug 843, this reveals some unsupported behavior
634 # my ($self, $value) = @_;
635 # if (index($value, $/) >= 0) {
636 # push @{$self->{'_readbuffer'}}, $value;
638 # $self->throw("Pushing modifed data back not supported: $value");
643 my ($self, $value) = @_;
644 return unless $value;
645 unshift @
{$self->{'_readbuffer'}}, $value;
654 Function: Closes the file handle associated with this IO instance,
655 excepted if -noclose was specified.
664 # do not close if we explicitly asked not to
665 return if $self->noclose;
667 if( defined( my $fh = $self->{'_filehandle'} )) {
669 return if ref $fh eq 'GLOB' && (
670 \
*STDOUT
== $fh || \
*STDERR
== $fh || \
*STDIN
== $fh
673 # don't close IO::Strings
674 CORE
::close $fh unless ref $fh && $fh->isa('IO::String');
676 $self->{'_filehandle'} = undef;
677 delete $self->{'_readbuffer'};
686 Function: Flushes the filehandle
695 if( !defined $self->{'_filehandle'} ) {
696 $self->throw("Flush failed: no filehandle was active");
699 if( ref($self->{'_filehandle'}) =~ /GLOB/ ) {
700 my $oldh = select($self->{'_filehandle'});
704 $self->{'_filehandle'}->flush();
713 Usage : $io->noclose($newval)
714 Function: Get or set the NOCLOSE flag - setting this to true will prevent a
715 filehandle from being closed when an object is cleaned up or
717 Args : Optional new value (a scalar or undef)
718 Returns : Value of noclose (a scalar)
724 return $self->{'_noclose'} = shift if @_;
725 return $self->{'_noclose'};
736 my $v = $self->verbose;
738 # we are planning to cleanup temp files no matter what
739 if ( exists($self->{'_rootio_tempfiles'})
740 and ref($self->{'_rootio_tempfiles'}) =~ /array/i
741 and not $self->save_tempfiles
744 warn( "going to remove files ",
745 join(",", @
{$self->{'_rootio_tempfiles'}}),
748 unlink (@
{$self->{'_rootio_tempfiles'}} );
750 # cleanup if we are not using File::Temp
751 if ( $self->{'_cleanuptempdir'}
752 and exists($self->{'_rootio_tempdirs'})
753 and ref($self->{'_rootio_tempdirs'}) =~ /array/i
754 and not $self->save_tempfiles
757 warn( "going to remove dirs ",
758 join(",", @
{$self->{'_rootio_tempdirs'}}),
761 $self->rmtree( $self->{'_rootio_tempdirs'});
769 Usage : $exists = $io->exists_exe('clustalw');
770 $exists = Bio::Root::IO->exists_exe('clustalw')
771 $exists = Bio::Root::IO::exists_exe('clustalw')
772 Function: Determines whether the given executable exists either as file
773 or within the path environment. The latter requires File::Spec
775 On Win32-based system, .exe is automatically appended to the program
776 name unless the program name already ends in .exe.
777 Args : Name of the executable
778 Returns : 1 if the given program is callable as an executable, and 0 otherwise
783 my ($self, $exe) = @_;
784 $self->throw("Must pass a defined value to exists_exe") unless defined $exe;
785 $exe = $self if (!(ref($self) || $exe));
786 $exe .= '.exe' if(($^O
=~ /mswin/i) && ($exe !~ /\.(exe|com|bat|cmd)$/i));
787 return $exe if ( -f
$exe && -x
$exe ); # full path and exists
789 # Ewan's comment. I don't think we need this. People should not be
790 # asking for a program with a pathseparator starting it
791 # $exe =~ s/^$PATHSEP//;
793 # Not a full path, or does not exist. Let's see whether it's in the path.
794 if($FILESPECLOADED) {
795 for my $dir (File
::Spec
->path()) {
796 my $f = Bio
::Root
::IO
->catfile($dir, $exe);
797 return $f if( -f
$f && -x
$f );
807 Usage : my ($handle,$tempfile) = $io->tempfile();
808 Function: Create a temporary filename and a handle opened for reading and
810 Caveats: If you do not have File::Temp on your system you should
811 avoid specifying TEMPLATE and SUFFIX.
812 Args : Named parameters compatible with File::Temp: DIR (defaults to
813 $Bio::Root::IO::TEMPDIR), TEMPLATE, SUFFIX.
814 Returns : A 2-element array, consisting of temporary handle and temporary
820 my ($self, @args) = @_;
824 # map between naming with and without dash
825 for my $key (keys(%params)) {
827 my $v = $params{$key};
828 delete $params{$key};
829 $params{uc(substr($key,1))} = $v;
831 # this is to upper case
832 my $v = $params{$key};
833 delete $params{$key};
834 $params{uc($key)} = $v;
837 $params{'DIR'} = $TEMPDIR if(! exists($params{'DIR'}));
838 unless (exists $params{'UNLINK'} &&
839 defined $params{'UNLINK'} &&
840 ! $params{'UNLINK'} ) {
841 $params{'UNLINK'} = 1;
843 $params{'UNLINK'} = 0;
846 if($FILETEMPLOADED) {
847 if(exists($params{'TEMPLATE'})) {
848 my $template = $params{'TEMPLATE'};
849 delete $params{'TEMPLATE'};
850 ($tfh, $file) = File
::Temp
::tempfile
($template, %params);
852 ($tfh, $file) = File
::Temp
::tempfile
(%params);
855 my $dir = $params{'DIR'};
856 $file = $self->catfile(
858 (exists($params{'TEMPLATE'}) ?
859 $params{'TEMPLATE'} :
860 sprintf( "%s.%s.%s", $ENV{USER
} || 'unknown', $$, $TEMPCOUNTER++))
863 # sneakiness for getting around long filenames on Win32?
865 $file = Win32
::GetShortPathName
($file);
868 # Try to make sure this will be marked close-on-exec
869 # XXX: Win32 doesn't respect this, nor the proper fcntl,
870 # but may have O_NOINHERIT. This may or may not be in Fcntl.
872 # Store callers umask
876 # Attempt to open the file
877 if ( sysopen($tfh, $file, $OPENFLAGS, 0600) ) {
881 $self->throw("Could not write temporary file '$file': $!");
885 if( $params{'UNLINK'} ) {
886 push @
{$self->{'_rootio_tempfiles'}}, $file;
889 return wantarray ?
($tfh,$file) : $tfh;
896 Usage : my ($tempdir) = $io->tempdir(CLEANUP=>1);
897 Function: Creates and returns the name of a new temporary directory.
899 Note that you should not use this function for obtaining "the"
900 temp directory. Use $Bio::Root::IO::TEMPDIR for that. Calling this
901 method will in fact create a new directory.
903 Args : args - ( key CLEANUP ) indicates whether or not to cleanup
904 dir on object destruction, other keys as specified by File::Temp
905 Returns : The name of a new temporary directory.
910 my ($self, @args) = @_;
911 if ($FILETEMPLOADED && File
::Temp
->can('tempdir')) {
912 return File
::Temp
::tempdir
(@args);
915 # we have to do this ourselves, not good
916 # we are planning to cleanup temp files no matter what
918 print "cleanup is " . $params{CLEANUP
} . "\n";
919 $self->{'_cleanuptempdir'} = ( defined $params{CLEANUP
} &&
920 $params{CLEANUP
} == 1);
921 my $tdir = $self->catfile( $TEMPDIR,
922 sprintf("dir_%s-%s-%s",
923 $ENV{USER
} || 'unknown',
927 push @
{$self->{'_rootio_tempdirs'}}, $tdir;
935 Usage : $path = Bio::Root::IO->catfile(@dirs, $filename);
936 Function: Constructs a full pathname in a cross-platform safe way.
938 If File::Spec exists on your system, this routine will merely
939 delegate to it. Otherwise it tries to make a good guess.
941 You should use this method whenever you construct a path name
942 from directory and filename. Otherwise you risk cross-platform
943 compatibility of your code.
945 You can call this method both as a class and an instance method.
947 Args : components of the pathname (directories and filename, NOT an
954 my ($self, @args) = @_;
956 return File
::Spec
->catfile(@args) if $FILESPECLOADED;
957 # this is clumsy and not very appealing, but how do we specify the
959 if($args[0] eq '/') {
962 return join($PATHSEP, @args);
969 Usage : Bio::Root::IO->rmtree($dirname );
970 Function: Remove a full directory tree
972 If File::Path exists on your system, this routine will merely
973 delegate to it. Otherwise it runs a local version of that code.
975 You should use this method to remove directories which contain
978 You can call this method both as a class and an instance method.
980 Args : roots - rootdir to delete or reference to list of dirs
982 verbose - a boolean value, which if TRUE will cause
983 C<rmtree> to print a message each time it
984 examines a file, giving the name of the file, and
985 indicating whether it's using C<rmdir> or
986 C<unlink> to remove it, or that it's skipping it.
989 safe - a boolean value, which if TRUE will cause C<rmtree>
990 to skip any files to which you do not have delete
991 access (if running under VMS) or write access (if
992 running under another OS). This will change in the
993 future when a criterion for 'delete permission'
994 under OSs other than VMS is settled. (defaults to
996 Returns : number of files successfully deleted
1000 # taken straight from File::Path VERSION = "1.0403"
1002 my ($self, $roots, $verbose, $safe) = @_;
1003 if ( $FILEPATHLOADED ) {
1004 return File
::Path
::rmtree
($roots, $verbose, $safe);
1007 my $force_writable = ($^O
eq 'os2' || $^O
eq 'dos' || $^O
eq 'MSWin32' ||
1008 $^O
eq 'amigaos' || $^O
eq 'cygwin');
1009 my $Is_VMS = $^O
eq 'VMS';
1015 if ( defined($roots) && length($roots) ) {
1016 $roots = [$roots] unless ref $roots;
1018 $self->warn("No root path(s) specified\n");
1023 for $root (@
{$roots}) {
1025 (undef, undef, my $rp) = lstat $root or next;
1026 $rp &= 07777; # don't forget setuid, setgid, sticky bits
1028 # notabene: 0777 is for making readable in the first place,
1029 # it's also intended to change it to writable in case we have
1030 # to recurse in which case we are better than rm -rf for
1031 # subtrees with strange permissions
1032 chmod(0777, ($Is_VMS ? VMS
::Filespec
::fileify
($root) : $root))
1033 or $self->warn("Could not make directory '$root' read+writable: $!")
1035 if (opendir DIR
, $root){
1036 @files = readdir DIR
;
1039 $self->warn("Could not read directory '$root': $!");
1043 # Deleting large numbers of files from VMS Files-11 filesystems
1044 # is faster if done in reverse ASCIIbetical order
1045 @files = reverse @files if $Is_VMS;
1046 ($root = VMS
::Filespec
::unixify
($root)) =~ s
#\.dir\z## if $Is_VMS;
1047 @files = map("$root/$_", grep $_!~/^\
.{1,2}\z
/s
,@files);
1048 $count += $self->rmtree([@files],$verbose,$safe);
1050 ($Is_VMS ?
!&VMS
::Filespec
::candelete
($root) : !-w
$root)) {
1051 print "skipped '$root'\n" if $verbose;
1055 or $self->warn("Could not make directory '$root' writable: $!")
1057 print "rmdir '$root'\n" if $verbose;
1062 $self->warn("Could not remove directory '$root': $!");
1063 chmod($rp, ($Is_VMS ? VMS
::Filespec
::fileify
($root) : $root))
1064 or $self->warn("and can't restore permissions to "
1065 . sprintf("0%o",$rp) . "\n");
1070 and ($Is_VMS ?
!&VMS
::Filespec
::candelete
($root)
1071 : !(-l
$root || -w
$root))
1073 print "skipped '$root'\n" if $verbose;
1077 or $self->warn( "Could not make file '$root' writable: $!")
1079 warn "unlink '$root'\n" if $verbose;
1080 # delete all versions under VMS
1082 unless (unlink $root) {
1083 $self->warn("Could not unlink file '$root': $!");
1084 if ($force_writable) {
1086 or $self->warn("and can't restore permissions to "
1087 . sprintf("0%o",$rp) . "\n");
1092 last unless $Is_VMS && lstat $root;
1101 =head2 _flush_on_write
1103 Title : _flush_on_write
1104 Usage : $io->_flush_on_write($newval)
1105 Function: Boolean flag to indicate whether to flush
1106 the filehandle on writing when the end of
1107 a component is finished (Sequences, Alignments, etc)
1108 Args : Optional new value
1109 Returns : Value of _flush_on_write
1113 sub _flush_on_write
{
1114 my ($self, $value) = @_;
1115 if (defined $value) {
1116 $self->{'_flush_on_write'} = $value;
1118 return $self->{'_flush_on_write'};
1122 =head2 save_tempfiles
1124 Title : save_tempfiles
1125 Usage : $io->save_tempfiles(1)
1126 Function: Boolean flag to indicate whether to retain tempfiles/tempdir
1127 Args : Value evaluating to TRUE or FALSE
1128 Returns : Boolean value : 1 = save tempfiles/tempdirs, 0 = remove (default)
1132 sub save_tempfiles
{
1136 $self->{save_tempfiles
} = $value ?
1 : 0;
1138 return $self->{save_tempfiles
} || 0;