in reply to printing contents of small files into one larger one

The following uses the <> operator to read all the files passed on the command line in a line at a time fashion. Each value is appended to a list in memory and then joined and printed when the internal file handle used by the diamond operator hits an end of file (see the description of eof in perlop for details).

#! /usr/bin/perl use strict; use warnings; my @line; while (<>) { chomp; push @line, "$_"; } continue { if (eof) { print join("\t", @line), "\n"; @line = (); close ARGV; } }
Update: Simplified. No need for an array or any fancy joining!
while (<>) { chomp; if (eof) {print "$_\n"} else {print "$_\t"} }

The order that the files are appended is taken from the order in which they are listed in @ARGV. This can be sorted before the files are processed.

Replies are listed 'Best First'.
Re^2: printing contents of small files into one larger one
by virtualsue (Vicar) on Nov 09, 2005 at 13:59 UTC
    That's cute, but it doesn't quite do what was asked. It prints each file's entries per output row, when what's needed is each file per output column. Unfortunately that transposition greatly complicates the task. Either you need to read all the files into memory in some data structure, or open all the files and for every line that is to be output, read one entry per filehandle (see holli's answer). For the sake of completeness, here's a way to read all the data into a "hash of arrays" data structure. The keys are the names of the data files, and the values are references to the data read from each data file.

    If the only goal here is to print out the data, I would do it holli's way. Reading all the files into memory into one big data structure wouldn't scale very well.

    #!/usr/bin/perl use warnings; use strict; use Data::Dumper; my @files = glob('data/*'); my %filedata; for my $file (@files) { open my $fh, "<$file" or die "Ack, Can't open $file"; chomp( my @data = <$fh> ); close $fh; $filedata{$file} = \@data; } print Dumper(\%filedata);
    $VAR1 = { 'test/bb' => [ '5.6', '5.7', '5.9' ], 'test/aa' => [ '1.3', '1.4', '1.5' ] };
      Fair enough. I should have read the question!

      I have modified the technique to build an AoA in memory before writing it out. The OP wasn't clear on how files of differing length were to be treated. The code below expands the AoA as necessary to cope with files of different lengths.

      my @lines; my $line = 0; my $filecount = 0; while (<>) { chomp (${$lines[$line++]}[$filecount] = $_); if (eof) { $line = 0; $filecount++; } } foreach (@lines) { $#{$_} = $filecount -1; print join("\t", @{$_}), "\n" ; }
Re^2: printing contents of small files into one larger one
by mlh2003 (Scribe) on Nov 09, 2005 at 12:41 UTC
    What's wrong with slurping each file into an array? As in
    my @line = <FH>;
    (where FH is the filehandle of the currently-opened file). Am I missing something?

    UPDATE:
    Aside from using a different approach to read the file into an array, the final output still needs to have the data transposed.
    _______
    Code is untested unless explicitly stated
    mlh2003