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

How do I append more than one files? For example, if I have 12 txt files that live in different directories, I want to append them all to one txt file in a given directory. This is similar to the Unix 'cat' command but I want a Perl script to do it! Thanks

Replies are listed 'Best First'.
Re: How do I append more than one files?
by davido (Cardinal) on Jun 16, 2004 at 06:50 UTC
    You would open a single file for append/output. You would then, open one input file, read it line by line, and as you read each line, write it back out to the output file. When you reach the end of the first file, you would then close it and open the second input file, and so on. Once you've repeated this process for each input file, you would then close the output file. Don't forget to check return values to ensure that your files are getting opened and closed properly, etc.

    You may be able to glean some understanding by reading the documentation for open. Also perlopentut may be helpful.

    Take a stab at it, and when you get hung up on some specific part of your implementation of a solution, follow-up to this thread with some specific questions.

    The general nature of this website tends to offer help and assistance in learning Perl. Requests for prewritten scripts generally aren't well received. If you're looking for someone to write a complete solution for you, post a job on http://jobs.perl.org.


    Dave

Re: How do I append more than one files?
by saskaqueer (Friar) on Jun 16, 2004 at 06:56 UTC

    This script does something like what you want:

    #!perl -w =head1 USAGE ./combine.pl output_file input_1 input_2 [..., input_x] Where output_file is the file to which all input files (input_1, input_2, ..., input_x) should be combined to. =cut use strict; my $out = shift @ARGV; open( my $out_fh, '>', $out ) or die("Could not open output file '$out': $!\n"); for my $file (@ARGV) { open( my $in_fh, '<', $file ) or die("Error opening '$file': $!\n"); print $out_fh $_ while (<$in_fh>); close($in_fh) or die("Error closing '$file': $!\n"); print $out_fh "\n"; } close($out_fh) or die("Error closing '$out': $!\n");

      This is certainly useful but in essence, would this take a longer time than usual? The reason being - we have 12 log files, running on 6 clones, and we are required to keep them for xx days but would like to 'cat' them ala Unix but the app server is running on Wintel boxes.

      So far the closest thing I can find in the ActivePerl manual is this command line:

      perl -MExtUtils::Command -e cat file1 file2 .. > merge_file

      If I want to pass the files as parameters, can I call the above command within another perl script? So I would have a Perl script called catFiles.pl file1 file 2 > merge_file and in the script, I would have:

      perl -MExtUtils::Command -e cat $arg[0] $arg1 > $arg3

      but it doesnt seem to work. At the moment, I could get it to work by creating a dos batch and passing the args to the perl command, but it is not ideal. Thanks again

        I think you'd want something like this to create your catFiles.pl script:

        #!perl # called as catFiles.pl input1 input2 > output exec( qw(perl -MExtUtils::Command -e cat), @ARGV );

        Or if you want a different way of executing the command:

        #!perl -w # called as catFiles.pl output input1 input2 use strict; my ($output, @inputs) = @ARGV; exec("perl -MExtUtils::Command -e cat @inputs > $output");
Re: How do I append more than one files?
by Not_a_Number (Prior) on Jun 16, 2004 at 08:04 UTC

    You don't need perl for this. In the shell:

    copy path\to\file1 + path\to\file2 + path\to\file3 path\to\newfile

      Strange things can happen if you want to copy binary files this way and forget the /B before the first argument (copy will stop at the first \cd). So:

      copy /b path\to\file1 + path\to\file2 + path\to\file3 path\to\newfile
        Strange things can happen if you want to copy binary files this way and forget the /B before the first argument (copy will stop at the first \cd)
        The solutions given so far will not deal with that, either. In a binary file, you're not at all guaranteed to have a newline. This (untested) code should work in the general case:
        use warnings; use strict; open(my $out, ">", shift(@ARGV) ) or die $!; my $buffer_length = 16_384; while( my $file = shift(@ARGV) ) { open(my $fh, $file) or die $!; while( read($fh, my $buffer, $buffer_length) ) { print $out $buffer or die $!; } close $fh; } close $out or die $!;
        Season to taste.

        thor

      The OP knew that there were other ways to do it, but wanted one in perl. One reason that I could see for this is cross-platform portability. If written correctly, the script will be able to run wherever perl is installed.

      thor

Re: How do I append more than one files?
by Anonymous Monk on Jun 16, 2004 at 06:45 UTC
    BTW, I forgot to mention that the Perl script should be in Win32 (ie ActivePer)