http://qs321.pair.com?node_id=751781

lomSpace has asked for the wisdom of the Perl Monks concerning the following question:

Hello,
I am trying to append the contents of three files to another file.
I am only appending the strings from my regex and not
the actual contents of the files. My code

#!/usr/bin/perl use strict; use Data::Dumper; use File::Glob ':glob'; my @dirs = glob("C:/Documents and Settings/mydir/Desktop/KOMP/*"); foreach my $maid_dir(@dirs){ if (-d $maid_dir){ # directory check if ($maid_dir=~m%\d+\s[A-Z]%){ # match the dir name my $seq_dir = $maid_dir."/sequencing/"; chdir ($maid_dir); next if (-M $seq_dir > 1.0); chdir ($seq_dir); #print Dumper ($maid_dir, $seq_dir); opendir my $dh, "$seq_dir"; if(-d $seq_dir){ my @files = readdir $dh; #my $path = @_; for my $f(@files){ if($f=~ m%^(\d*)(HU.fa|HD.fa|Ltvec_small.FA|_fasta +)$%){ my ($fa, $hu, $hd, $lt)= ($1."_fasta", $1."HU. +fa", $1."HD.fa", $1."Ltvec_small.FA"); if(-e $fa){ open( my $in, ">>".$seq_dir."/".$fa); #open( my $out, ">>".$seq_dir."/".$fa); print $in, "\n" ;#"$hu,$hd,$lt\n"; print Dumper($f); close($in); } } } } } } }
gets me into the proper dir to access the files but I am
doing something stupid. Any ideas?

Replies are listed 'Best First'.
Re: appending to a file
by Fletch (Bishop) on Mar 19, 2009 at 16:38 UTC

    Not checking the return value from things like chdir, opendir, or open certainly could be considered stupid.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

      fletch++

      To give a more direct example of what Fletch is talking about, do you know what happens in this piece of code if the change directory does not exist?

      my $dir = "/my/working/directory"; chdir ( $dir ); system ("rm -rf *");
        This removes everything in the dir.

      I checked the return values of chdir with Dumper. $in gives me
      a glob memory address. I know that I am in the correct dir
      because my regex matches the file names.

        It will always give you a glob memory address
        #!/usr/bin/perl -- use Data::Dumper; use strict; use warnings; opendir my $dh, "doesnotexist.mustnotexist"; print Dumper( $dh); __END__ $VAR1 = \*{'::$dh'}; D:\dev\misc> D:\dev\misc>perl #!/usr/bin/perl -- use Data::Dumper; use strict; use warnings; for my $dir( "doesnotexist.mustnotexist", "."){ opendir my $dh, $dir; Parentheses missing around "my" list at - line 7. print "dir $dir ", Dumper( $dh); } __END__ dir doesnotexist.mustnotexist $VAR1 = \*{'::$dh'}; dir . $VAR1 = \*{'::$dh'};
        system calls can fail for any reason
Re: appending to a file
by lostjimmy (Chaplain) on Mar 19, 2009 at 17:29 UTC

    I think the problem in your script is your print line. You have:

    print $in, "\n" ;#"$hu,$hd,$lt\n"
    which I'm assuming you were originally trying to print what is in comments.

    What you would really want is:

    print $in "$hu,$hd,$lt\n"; # no comma between $in and "..."

    Other important things:

    • Check errors after everything (chdir, open, opendir, close). If that doesn't work, you can even make sure print completed successfully.
    • You should make more use of string interpolation. It would make your code cleaner. That is, use open my $in, ">>$seq_dir/$fa" instead.
    • It's generally considered better form to use the three argument version of open, so change your open lines to open my $in, ">>", "$seq_dir/$fa"; and similar.
Re: appending to a file
by Nkuvu (Priest) on Mar 19, 2009 at 16:41 UTC

    I'd start with error checking. (added: Fletch is more accurate than I am on the functions you'll want to check errors on, consider adding similar error checking to the functions mentioned):
    open( my $in, ">>".$seq_dir."/".$fa) or die "Unable to open $seq_dir/$fa for append: $!\n";
    Obviously if the file is read only or the path isn't parsed correctly, the open call will fail and you won't be able to write to the file.

      I can append to the file, but am having trouble accessing the file contents. I am
      appending the file names not the contents. Example
      13132HU.fa,13132HD.fa,13132Ltvec_small.FA 13132HU.fa,13132HD.fa,13132Ltvec_small.FA 13132HU.fa,13132HD.fa,13132Ltvec_small.FA 13132HU.fa,13132HD.fa,13132Ltvec_small.FA
      This is what is being appended to the file. I want the contents
      of those files to be appended to the file.
      Any ideas?

        I can't see how that's possible. The only thing you append to the file is a newline.

        Here's a guess on what you're really looking for. You want to append the three files to the $fa file. You'll need to open each in turn, read from it, then print the contents to the $fa file (those variable names could really be more descriptive, by the way).

        So I think what you want is something like this:

        #!/usr/bin/perl use strict; use Data::Dumper; use File::Glob ':glob'; my @dirs = glob("C:/Documents and Settings/mydir/Desktop/KOMP/*"); foreach my $maid_dir (@dirs) { # Combined the first two conditionals to reduce indentation if (-d $maid_dir and $maid_dir=~m%\d+\s[A-Z]%){ # match the dir na +me my $seq_dir = $maid_dir."/sequencing/"; chdir ($maid_dir) or die "Can't chdir to $maid_dir: $!\n"; next if (-M $seq_dir > 1.0); chdir ($seq_dir) or die "Can't chdir to $seq_dir: $!\n"; #print Dumper ($maid_dir, $seq_dir); opendir my $dh, "$seq_dir" or die "Can't open $seq_dir: $!\n"; if(-d $seq_dir){ my @files = readdir $dh; #my $path = @_; for my $f(@files){ if($f=~ m%^(\d*)(HU.fa|HD.fa|Ltvec_small.FA|_fasta)$%) +{ my ($fa, $hu, $hd, $lt)= ($1."_fasta", $1."HU.fa", + $1."HD.fa", $1."Ltvec_small.FA"); if(-e $fa){ # This is output, not input. Renamed variable +accordingly. open( my $out, ">>".$seq_dir."/".$fa) or die " +Can't open $seq_dir/$fa for append: $!\n"; # Append the contents of the three files to $f +a open my $hu_file, '<', $hu or die "Can't open +$hu: $!\n"; while (my $line = <$hu_file>) { print $out $line; } open my $hd_file, '<', $hd or die "Can't open +$hd: $!\n"; while (my $line = <$hd_file>) { print $out $line; } open my $lt_file, '<', $lt or die "Can't open +$lt: $!\n"; while (my $line = <$lt_file>) { print $out $line; } #open( my $out, ">>".$seq_dir."/".$fa); print $out, "\n" ;#"$hu,$hd,$lt\n"; print Dumper($f); close($out); close($hu_file); close($hd_file); close($lt_file); } } } } } }

        Note that this is a very quick revision of your code, with added error checks (and just noticed I missed the readdir, doh). And it may not be at all what you want. If not, please provide more detail on what you're trying to do.

      The file test has not failed

        The -e checks for the existence of a file, not writability. So the file test in question won't guarantee that your file can be opened for appending.

        A reply falls below the community's threshold of quality. You may see it by logging in.