Perl command to copy one file into another file?

B

Bill

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?
 
K

ko

Bill said:
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
 
B

Bill

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;
}
}
 
K

ko

Bill said:
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;
}
}

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
 
M

Michael P. Broida

Bill said:
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
 
B

Bill

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 said:
Bill said:
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;
}
}

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
 
E

Eric Schwartz

Bill said:
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 = $_;

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$/ said:

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
 
K

ko

Bill said:
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
 
J

Jay Tilton

[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.]


: 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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top