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

Hi , I want to copy the contents of a file say "tmp" to another file say "LOG" if a certain condition matches. It works great but the problem is everytime the condition is evaluated "true" it overwrites the complete LOG instead of appending tmp to LOG. Is there any way i can overcome this. I am aware that i can assign a handle to tmp and then append using >> operator and read file using while loop and then print it to the "LOG" or do it using foreach ()after dumping everything into an array. BUT I WANT MY CODE TO BE ROBUST OR HAVE OTHER SIMPLE WAY TO DO IT RATHER THAN doing it in the above described way... Any sugestions ?? copy("tmp","LOG") or die "Copy failed: $!"; Can this be manipulated in a line or two rather than using file handles AND WHILE/foreach LOOP and print ? And also I tried to used cat ("tmp >> LOG") isntead of copy but nothing is copied from tmp to LOG after execution.. -Thanks Ram

Replies are listed 'Best First'.
Re: Is there a way to avoid copy function from overwriting old contents?
by JavaFan (Canon) on Apr 12, 2011 at 06:38 UTC
    This ought to work:
    use autodie; use File::Copy 'copy'; my $append = ...; # If true append, else overwrite. open my $fh, $append ? ">>" : ">", LOG; copy "tmp", $fh;
    Or:
    my $append = ...; # If true append, else overwrite. system "cat tmp " . ($append ? ">>" : ">") . " LOG" and die;
      Hi all, Thanks for the help. @Java fan : Thank you, your suggestion with slight modification seems to work best for my case. -Ram
Re: Is there a way to avoid copy function from overwriting old contents?
by ww (Archbishop) on Apr 12, 2011 at 00:34 UTC
    Do you have the misconception that appending to a file is somehow non-robust?

    In any case, perhaps showing us the code that you say "works great" and telling us how it falls short of your desires will let us help you more directly.

      Hi , My code is dependent on the output coming from a hardware , so couldnt share it earlier !! here's the simple form of my code
      #!/usr/bin/perl use strict; use warnings; use File::Copy; my $value0 = 1; #change this to 0 and execute a +nd back to one and execute my $value1 ='true'; open (INFO, "> tmp"); print INFO "this is simple\n"; close (INFO); open (FILE, ">> RESULT_LOG") ; print FILE " STATUS obtained : $value1\n"; if ($value0 == 1) { # If true then copies the informa +tion to the RESULT_LOG copy("tmp","RESULT_LOG");} else { print FILE "Check keyword supplied\n";} close(FILE);
      You can run it once. It will create result_log and tmp files. Change the input my $value0 = 0; and run again ..Note: that it will append the result to the result_log. NOW change the my $value0 = 1; and run it again it will replace the result_log to have only recent output.So bottomline : After 1st true no matter how many false inputs it continues to append until it finds the true vondition again. So my question here is that , is it possible to stop replacing the old log and continue to append ? Note: I also found something strange. The line "this is simple" is appemded to the log file before the actual print.How is that possible ? -Thanks Ram

        Replace:

        copy("tmp", "RESULT_LOG");

        with:

        open my $tmpIn, '<', "tmp" or die "Failed to open tmp: $!"; open my $log, '>>', or die "Failed to open RESULT_LOG: $!"; print {$log} <$tmpIn>; close $log; close $tmpIn;

        Copy overwrites so that is not what you wanted.

        Note: you should always use three parameter open and lexical file handles.

        True laziness is hard work
        #!/usr/bin/perl use strict; use warnings; use File::Copy; #change this to 0 and execute, then back to one and execute my $value0 = 1; my $value1 ='true'; ## marmot: open for overwriting open (INFO, "> tmp"); print INFO "this is simple\n"; close (INFO); ## marmot: open RESULT_LOG for appending open (FILE, ">> RESULT_LOG") ; print FILE " STATUS obtained : $value1\n"; # If true then copies the information to the RESULT_LOG ## marmot: translation --> if $value0 is true, overwrite RESULT_LOG wi +th tmp. ## By the way, <FILE>, which is RESULT_LOG, is still open for +appending, ## so this is probably a bad idea. if ($value0 == 1) { copy("tmp","RESULT_LOG");} ## marmot: Otherwise, append RESULT_LOG with text. else { print FILE "Check keyword supplied\n"; } close(FILE);
        Apart from confusing copying with appending, and trying to overwrite a file that's already open for appending, this code can be made to work with the changes below.
        if ($value0 == 1) { open INFO, "<tmp"; print FILE <INFO>; # Appends to RESULT_LOG else { print FILE "Check keyword supplied\n"; } close(FILE); close(INFO);

        I realize this is just a snippet to show what you're trying to accomplish, but I have to wonder if it makes sense to open 'tmp' and write text to it, when you're just going to append it to another file later. Why not put this information in a variable and keep it around until you need to write it to a file?

        Also, for the sake of your own clarity, you might want to give your file handles names that are closer to the file names they represent, or perhaps the functions they perform. E.g.,

        open TMP, "<tmp"; open LOG, ">>RESULT_LOG"; open RESULTS, ">>RESULT_LOG";

        --marmot

Re: Is there a way to avoid copy function from overwriting old contents?
by GrandFather (Saint) on Apr 12, 2011 at 00:39 UTC

    Show us your current copy code. On the face of it you should just need something like:

    open my $tmpIn, '<', $temp or die "Failed to open $temp: $!\n"; open my $logOut, '>>', $log or die "Failed to open $log: $!\n"; print {$logOut} <$tmpIn>;
    True laziness is hard work
      Hi , Thanks.Replied above. trying your suggestion now.