Perl command to copy one file into another file?

Discussion in 'Perl Misc' started by Bill, Sep 27, 2003.

  1. Bill

    Bill Guest

    Is there a single Perl command to copy file 1 into file 2 with out going
    through the where-with-all of a while loop? Thanks, Bill

    Perl command to copy one file into another file?
     
    Bill, Sep 27, 2003
    #1
    1. Advertising

  2. Bill

    ko Guest

    Bill wrote:
    > Is there a single Perl command to copy file 1 into file 2 with out going
    > through the where-with-all of a while loop? Thanks, Bill
    >
    > Perl command to copy one file into another file?
    >
    >


    The File::Copy module.

    use File::Copy;
    copy("file1","file2") or die "Copy failed: $!";

    'perldoc File::Copy' gives you all the details

    HTH - keith
     
    ko, Sep 27, 2003
    #2
    1. Advertising

  3. Bill

    Bill Guest

    while ( <INPUT1> ) {
    # print "Reading $ARGV[0]\n";
    print OUTPUT $_;
    }

    The copy statment, copy("file1","file2") or die "Copy failed: $!"; is
    supposed to replace the above while statement.

    I get this error with the copy statment ...
    C:\PERL1\OUTPUT7>bbbb5.pl output5.txt output6.txt output7.txt
    Undefined subroutine &main::copy called at C:\PERL1\OUTPUT7\bbbb5.pl line
    24.

    This is the script code ...

    open (INPUT1, "$ARGV[0]") or die "Cannot open $ARGV[0]";
    open (OUTPUT, "> $ARGV[2]");

    #print "First input file is: $ARGV[0]\n";
    #print "Second input file is: $ARGV[1]\n";
    #print "The output file is: $ARGV[2]\n\n";

    # This half of the code dumps everything in 'file1' to the output 'file3'
    # while ( <INPUT1> ) {
    # print "Reading $ARGV[0]\n";
    # print OUTPUT $_;
    # }

    File :: COPY;
    copy("$ARGV[0]","$ARGV[2]") or die "Copy failed: $!";

    # This half of the code compares 'file2' to 'file1' and writes out
    # any line that doesn't match to the output 'file3'

    open (INPUT1, "$ARGV[1]") or die "Cannot open $ARGV[1]";

    while ( <INPUT1> ) {
    $match = 0;

    $a = $_;
    open (INPUT2, "$ARGV[0]") or die "Cannot open $ARGV[0]";
    while ( <INPUT2> ) {
    $b = $_;
    if ($a eq $b) {
    $match = 1;
    last;
    }
    }

    if ($match == 0) {
    print OUTPUT $a;
    }
    }

    "ko" <> wrote in message
    news:bl37di$j2a$...
    > Bill wrote:
    > > Is there a single Perl command to copy file 1 into file 2 with out going
    > > through the where-with-all of a while loop? Thanks, Bill
    > >
    > > Perl command to copy one file into another file?
    > >
    > >

    >
    > The File::Copy module.
    >
    > use File::Copy;
    > copy("file1","file2") or die "Copy failed: $!";
    >
    > 'perldoc File::Copy' gives you all the details
    >
    > HTH - keith
    >
     
    Bill, Sep 29, 2003
    #3
  4. Bill

    ko Guest

    Bill wrote:

    > while ( <INPUT1> ) {
    > # print "Reading $ARGV[0]\n";
    > print OUTPUT $_;
    > }
    >
    > The copy statment, copy("file1","file2") or die "Copy failed: $!"; is
    > supposed to replace the above while statement.
    >
    > I get this error with the copy statment ...
    > C:\PERL1\OUTPUT7>bbbb5.pl output5.txt output6.txt output7.txt
    > Undefined subroutine &main::copy called at C:\PERL1\OUTPUT7\bbbb5.pl line
    > 24.
    >
    > This is the script code ...
    >
    > open (INPUT1, "$ARGV[0]") or die "Cannot open $ARGV[0]";
    > open (OUTPUT, "> $ARGV[2]");
    >
    > #print "First input file is: $ARGV[0]\n";
    > #print "Second input file is: $ARGV[1]\n";
    > #print "The output file is: $ARGV[2]\n\n";
    >
    > # This half of the code dumps everything in 'file1' to the output 'file3'
    > # while ( <INPUT1> ) {
    > # print "Reading $ARGV[0]\n";
    > # print OUTPUT $_;
    > # }
    >
    > File :: COPY;


    When you 'use' a module case matters, and you forgot 'use'. It should be:

    use File::Copy;

    That's the reason for the 'undefined subroutine...' error message.

    > copy("$ARGV[0]","$ARGV[2]") or die "Copy failed: $!";
    >
    > # This half of the code compares 'file2' to 'file1' and writes out
    > # any line that doesn't match to the output 'file3'
    >
    > open (INPUT1, "$ARGV[1]") or die "Cannot open $ARGV[1]";
    >
    > while ( <INPUT1> ) {
    > $match = 0;
    >
    > $a = $_;
    > open (INPUT2, "$ARGV[0]") or die "Cannot open $ARGV[0]";
    > while ( <INPUT2> ) {
    > $b = $_;
    > if ($a eq $b) {
    > $match = 1;
    > last;
    > }
    > }
    >
    > if ($match == 0) {
    > print OUTPUT $a;
    > }
    > }
    >
    > "ko" <> wrote in message
    > news:bl37di$j2a$...
    >
    >>Bill wrote:
    >>
    >>>Is there a single Perl command to copy file 1 into file 2 with out going
    >>>through the where-with-all of a while loop? Thanks, Bill
    >>>
    >>>Perl command to copy one file into another file?
    >>>
    >>>

    >>
    >>The File::Copy module.
    >>
    >>use File::Copy;
    >>copy("file1","file2") or die "Copy failed: $!";
    >>
    >>'perldoc File::Copy' gives you all the details
    >>
    >>HTH - keith
    >>


    Maybe I misunderstood what you want to do. In your original post you
    stated that you want to copy a file without using a while loop. Above,
    however. the contents of the files are being compared. If you want to
    compare contents you do need a while loop.

    File::Copy does a straight copy, nothing else:

    #!/usr/bin/perl -w
    use strict;

    use File::Copy;
    die "Usage: SCRIPTNAME file1 file2\n" unless @ARGV == 2;
    copy($ARGV[0], $ARGV[1]) or die "Copy failed: $!";

    You should also add a check to see that the new file doesn't already
    exist (it will clobber an existing file), and pass the files with
    absolute paths.

    HTH - keith
     
    ko, Sep 30, 2003
    #4
  5. Bill wrote:
    >
    > Is there a single Perl command to copy file 1 into file 2 with out going
    > through the where-with-all of a while loop? Thanks, Bill
    >
    > Perl command to copy one file into another file?


    If you know EXACTLY what kind of system it will run on,
    (Windows, Linux, etc) you can use whatever command you
    would give to a shell or commandprompt.

    Use the ` (backtick) command in perl to run the shell
    command:

    $result = `copy a.txt b.txt`;

    $result will contain whatever output the shell returned
    (error messages, success message, whatever). Probably
    nothing if it was successful.

    Note that that method is not necessarily "portable".

    Mike
     
    Michael P. Broida, Sep 30, 2003
    #5
  6. Bill

    Bill Guest

    The objective is to create a sum of the two files with out any duplications.
    I included "use" into the script, but all it does now is make the file copy
    and loops with out making any comapisons with output6.txt.

    # To use this script, type the following at the command line prompt:
    # bbb.pl file1 file2 output_file_name

    open (INPUT1, "$ARGV[0]") or die "Cannot open $ARGV[0]";
    open (OUTPUT, "> $ARGV[2]");

    #print "First input file is: $ARGV[0]\n";
    #print "Second input file is: $ARGV[1]\n";
    #print "The output file is: $ARGV[2]\n\n";

    # This half of the code dumps everything in 'file1' to the output 'file3'

    #while ( <INPUT1> ) {
    # print "Reading $ARGV[0]\n";
    # print OUTPUT $_;
    #}

    use File::Copy;
    copy("$ARGV[0]","$ARGV[2]") or die "Copy failed: $!";

    # This half of the code compares 'file2' to 'file1' and writes out
    # any line that doesn't match to the output 'file3'

    open (INPUT1, "$ARGV[1]") or die "Cannot open $ARGV[1]";

    while ( <INPUT1> ) {
    $match = 0;

    $a = $_;
    open (INPUT2, "$ARGV[0]") or die "Cannot open $ARGV[0]";
    while ( <INPUT2> ) {
    $b = $_;
    if ($a eq $b) {
    $match = 1;
    last;
    }
    }

    if ($match == 0) {
    print OUTPUT $a;
    }
    }

    This is the dir from the command prompt. The script has been running all
    night and the output file, output7.txt, is still only as big as the file it
    copied yesterday, output5.txt. Output7.txt, the output file should be
    growing as comparisons are made with output6.txt.

    Directory of C:\PERL1\OUTPUT7

    09/29/2003 02:12p <DIR> .
    09/29/2003 02:12p <DIR> ..
    09/19/2003 10:28p 951 bbbb4.pl
    09/30/2003 01:47a 1,291 bbbb5.pl
    09/20/2003 07:50p <DIR> Output5
    09/20/2003 05:28p 3,965,417 output5.txt
    09/20/2003 02:37a <DIR> Output6
    09/20/2003 01:24p 3,775,496 output6.txt
    09/20/2003 05:28p 3,965,417 output7.txt
    5 File(s) 11,708,572 bytes
    4 Dir(s) 102,161,915,904 bytes free

    C:\PERL1\OUTPUT7>


    "ko" <> wrote in message
    news:blag3m$qmr$...
    > Bill wrote:
    >
    > > while ( <INPUT1> ) {
    > > # print "Reading $ARGV[0]\n";
    > > print OUTPUT $_;
    > > }
    > >
    > > The copy statment, copy("file1","file2") or die "Copy failed: $!"; is
    > > supposed to replace the above while statement.
    > >
    > > I get this error with the copy statment ...
    > > C:\PERL1\OUTPUT7>bbbb5.pl output5.txt output6.txt output7.txt
    > > Undefined subroutine &main::copy called at C:\PERL1\OUTPUT7\bbbb5.pl

    line
    > > 24.
    > >
    > > This is the script code ...
    > >
    > > open (INPUT1, "$ARGV[0]") or die "Cannot open $ARGV[0]";
    > > open (OUTPUT, "> $ARGV[2]");
    > >
    > > #print "First input file is: $ARGV[0]\n";
    > > #print "Second input file is: $ARGV[1]\n";
    > > #print "The output file is: $ARGV[2]\n\n";
    > >
    > > # This half of the code dumps everything in 'file1' to the output

    'file3'
    > > # while ( <INPUT1> ) {
    > > # print "Reading $ARGV[0]\n";
    > > # print OUTPUT $_;
    > > # }
    > >
    > > File :: COPY;

    >
    > When you 'use' a module case matters, and you forgot 'use'. It should be:
    >
    > use File::Copy;
    >
    > That's the reason for the 'undefined subroutine...' error message.
    >
    > > copy("$ARGV[0]","$ARGV[2]") or die "Copy failed: $!";
    > >
    > > # This half of the code compares 'file2' to 'file1' and writes out
    > > # any line that doesn't match to the output 'file3'
    > >
    > > open (INPUT1, "$ARGV[1]") or die "Cannot open $ARGV[1]";
    > >
    > > while ( <INPUT1> ) {
    > > $match = 0;
    > >
    > > $a = $_;
    > > open (INPUT2, "$ARGV[0]") or die "Cannot open $ARGV[0]";
    > > while ( <INPUT2> ) {
    > > $b = $_;
    > > if ($a eq $b) {
    > > $match = 1;
    > > last;
    > > }
    > > }
    > >
    > > if ($match == 0) {
    > > print OUTPUT $a;
    > > }
    > > }
    > >
    > > "ko" <> wrote in message
    > > news:bl37di$j2a$...
    > >
    > >>Bill wrote:
    > >>
    > >>>Is there a single Perl command to copy file 1 into file 2 with out

    going
    > >>>through the where-with-all of a while loop? Thanks, Bill
    > >>>
    > >>>Perl command to copy one file into another file?
    > >>>
    > >>>
    > >>
    > >>The File::Copy module.
    > >>
    > >>use File::Copy;
    > >>copy("file1","file2") or die "Copy failed: $!";
    > >>
    > >>'perldoc File::Copy' gives you all the details
    > >>
    > >>HTH - keith
    > >>

    >
    > Maybe I misunderstood what you want to do. In your original post you
    > stated that you want to copy a file without using a while loop. Above,
    > however. the contents of the files are being compared. If you want to
    > compare contents you do need a while loop.
    >
    > File::Copy does a straight copy, nothing else:
    >
    > #!/usr/bin/perl -w
    > use strict;
    >
    > use File::Copy;
    > die "Usage: SCRIPTNAME file1 file2\n" unless @ARGV == 2;
    > copy($ARGV[0], $ARGV[1]) or die "Copy failed: $!";
    >
    > You should also add a check to see that the new file doesn't already
    > exist (it will clobber an existing file), and pass the files with
    > absolute paths.
    >
    > HTH - keith
    >
     
    Bill, Sep 30, 2003
    #6
  7. "Bill" <> writes:
    > The objective is to create a sum of the two files with out any duplications.
    > I included "use" into the script, but all it does now is make the file copy
    > and loops with out making any comapisons with output6.txt.


    Here's the problem: we're not psychic. You asked for a solution that
    copied one file to another, and you got that. Now you appear to want
    to roll your own version of diff(1), instead. We can't help you
    unless we know what you actually want-- if you ask for something else,
    don't be surprised if you get that instead.

    > # To use this script, type the following at the command line prompt:
    > # bbb.pl file1 file2 output_file_name
    >
    > open (INPUT1, "$ARGV[0]") or die "Cannot open $ARGV[0]";


    Useless use of quotes, and you didn't use $! in your error string:

    open (INPUT1, $ARGV[0]) or die "Cannot open $ARGV[0]: $!";


    Also, every Perl program you write should begin with:

    #!/path/to/perl # please put the REAL path to perl here!!!
    use warnings;
    use strict;

    > open (OUTPUT, "> $ARGV[2]");


    Why didn't you die() on error here, too?

    open (OUTPUT, "> $ARGV[2]") or die "Cannot open $ARGV[2]: $!";

    Only that's wrong, you don't want to do that here. Wait until after
    you've done the copy, and THEN open it for append, not write.

    > #print "First input file is: $ARGV[0]\n";
    > #print "Second input file is: $ARGV[1]\n";
    > #print "The output file is: $ARGV[2]\n\n";
    >
    > # This half of the code dumps everything in 'file1' to the output 'file3'
    >
    > #while ( <INPUT1> ) {
    > # print "Reading $ARGV[0]\n";
    > # print OUTPUT $_;
    > #}
    >
    > use File::Copy;
    > copy("$ARGV[0]","$ARGV[2]") or die "Copy failed: $!";


    copy($ARGV[0], $ARGV[2]) or die "Copy failed: $!";

    There's no need to quote variables by themselves like that. It can
    even cause problems in some cases. Stop doing that.

    Also, everything that happened before happens now-- i.e., after the
    copy() call is through, file3 is an exact copy of file1.

    > # This half of the code compares 'file2' to 'file1' and writes out
    > # any line that doesn't match to the output 'file3'
    >
    > open (INPUT1, "$ARGV[1]") or die "Cannot open $ARGV[1]";


    open(INPUT1, $ARGV[1] or die "Cannot open $ARGV[1]: $!";

    Why are you re-opening INPUT1 here? You're using INPUT2 below, but
    you never open it. Are you meaning to do that here?

    You also want to open $ARGV[2] for output here:

    open(OUTPUT, '>>', $ARGV[2]) or die "couldn't open $ARGV[2] for append: $!";

    > while ( <INPUT1> ) {
    > $match = 0;
    >
    > $a = $_;


    while(my $a = <INPUT1>) {
    $match = 0;

    > open (INPUT2, "$ARGV[0]") or die "Cannot open $ARGV[0]";


    open (INPUT2, $ARGV[0]) or die "Cannot open $ARGV[0]: $!";

    > while ( <INPUT2> ) {
    > $b = $_;
    > if ($a eq $b) {
    > $match = 1;
    > last;
    > }
    > }
    >
    > if ($match == 0) {
    > print OUTPUT $a;
    > }


    Ick. Try this (untested)

    print OUTPUT $a unless grep /^\Q$a\E$/, <INPUT2>;

    > }


    This is a mess, and I'm fairly sure none of it does either what you
    think it does, or what you want it to. First, you read a line from
    the second input file. Then you assign it to $a. Remember, INPUT1 is
    a filehandle for the contents of $ARGV[1].

    Then you read from INPUT2, which you never opened, so naturally
    nothing is read. If you'd enabled warnings, perl would have said
    something like: "readline() on unopened filehandle INPUT2 at - line
    <foo>." Anyway, the logic is completely reversed-- after the copy,
    file3 is the same as file1, so you should isntead read file2, and then
    print out whatever's in that file that is NOT in file1.

    First off, this is a generally horrible solution, as you have to read
    through the entire contents of file1 EACH BLOODY TIME, which means
    horrid runtimes. A much better solution is to read both files, once,
    into a hash, and let that handle uniqueness for you:

    #!/usr/bin/perl
    use warnings;
    use strict;

    my $output = pop @ARGV;
    my %lines = ();
    while(<>) {
    chomp;
    $lines{$_}++;
    }

    open(OUTPUT, '>', $output) or die "couldn't open $output: $!";
    print OUTPUT join("\n", keys %lines), "\n";

    There's probably even better solutions; this is just off the top of my
    head.

    -=Eric
    --
    Come to think of it, there are already a million monkeys on a million
    typewriters, and Usenet is NOTHING like Shakespeare.
    -- Blair Houghton.
     
    Eric Schwartz, Sep 30, 2003
    #7
  8. Bill

    ko Guest

    "Bill" <> wrote in message news:<P4heb.1765$>...
    > The objective is to create a sum of the two files with out any duplications.
    > I included "use" into the script, but all it does now is make the file copy
    > and loops with out making any comapisons with output6.txt.
    >



    [snip]


    Ok, I mentioned this already, but File::Copy will *NOT* do what you
    are looking for. It copies files, *nothing* else. When you use the
    module there is no need to open filehandles, loop through the files,
    etc., you simply pass the pathnames to the files. Please read the
    documentation...

    So forget about File::Find in your code.

    One way to accomplish your task is:

    1. Build an array for file1 that consists of all lines in file1. Do
    the same for the second file - this can be done in one step.

    2. Build a hash where the keys are the elements of the arrays created
    above

    3. Print out the hash keys to the third file.

    Basically what you want is a 'union' of the two files. The code is
    available in perlfaq4, 'How do I compute the difference of two arrays?
    How do I compute the intersection of two arrays?' You can cut and
    paste the example code, but you only need the @union array ((@array1
    and @array2 will represent the two arrays in step 1).

    One last suggestion. Try to be more specific when you post a question.
    The original post and this last post are entirely different questions.

    HTH - keith
     
    ko, Sep 30, 2003
    #8
  9. Bill

    Jay Tilton Guest

    [Please do not top-post replies. Please trim reply-quoted material to
    the minimum necessary to establish context. See the clpm posting
    guidelines at http://mail.augustmail.com/~tadmc/clpmisc.shtml for
    explanations and other good advices.]

    "Bill" <> wrote:

    : The objective is to create a sum of the two files with out any duplications.

    This problem is a variation on finding the elements in one array that
    are not in another, which was discussed very recently in the thread
    "Find what is in array1 and not in array2." You might find the
    algorithms presented in that thread useful.

    : I included "use" into the script, but all it does now is make the file copy
    : and loops with out making any comapisons with output6.txt.
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    I doubt that's true. Just because you don't see evidence that it's
    happening doesn't mean it's not happening.

    : # To use this script, type the following at the command line prompt:
    : # bbb.pl file1 file2 output_file_name
    :
    : open (INPUT1, "$ARGV[0]") or die "Cannot open $ARGV[0]";
    ^ ^
    ^ ^
    Useless use of quotes.
    See perlfaq4, ' What's wrong with always quoting "$vars"? '

    : open (OUTPUT, "> $ARGV[2]");

    Always check the return from open() for success.

    open (OUTPUT, "> $ARGV[2]")
    or die "Cannot open $ARGV[2]: $!";

    : use File::Copy;
    : copy("$ARGV[0]","$ARGV[2]") or die "Copy failed: $!";
    ^ ^ ^ ^
    ^ ^ ^ ^ More UUoQ.

    Copying over a file while it is open feels like a bad idea. Better to
    copy the file first, then open the output file for appending.

    [snip rest of code]

    : The script has been running all night

    Comparing each line in one file with each line in another is going to be
    slow--very slow when those files are each 3-meg long. Imagine reading
    one 9-terabyte file to get an idea of scale.

    : and the output file, output7.txt, is still only as big as the file it
    : copied yesterday, output5.txt.

    The file's size, as reported by "dir", is not updated until the file is
    closed.
     
    Jay Tilton, Oct 1, 2003
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alex
    Replies:
    2
    Views:
    1,293
  2. Replies:
    26
    Views:
    2,184
    Roland Pibinger
    Sep 1, 2006
  3. Robert Cohen
    Replies:
    3
    Views:
    311
    Andrew Durstewitz
    Jul 15, 2003
  4. Bill
    Replies:
    6
    Views:
    1,538
    Michael P. Broida
    Sep 30, 2003
  5. Replies:
    2
    Views:
    172
    Tad McClellan
    Mar 26, 2005
Loading...

Share This Page