in reply to Merging files

OK, this isn't shorter, but it will merge as many files as you want, and lets you choose the name of the output file from the command-line. :-)
#! /usr/bin/perl use strict; use Getopt::Std; use Symbol; use vars qw(@handles $opt_f); getopts('f:'); if ($opt_f) { open (STDOUT, ">$opt_f") or die "Cannot write to $opt_f: $!"; } unless (@ARGV) { die "Usage: mergefile [-o<output_file>] file1 file2"; } foreach my $file (@ARGV) { my $fh = gensym; # Letting someone pipe from a cmd is useful enough to allow # having someone try to wipe out a file with ">". open ($fh, $file) or die "Cannot read from $file: $!"; push @handles, $fh; } while (@handles) { my $fh = shift @handles; if (defined( my $line = <$fh> )) { print $line; push @handles, $fh; } # else $fh goes out of scope here and autocloses }

Replies are listed 'Best First'.
RE: RE (tilly) 1: Merging files
by merlyn (Sage) on Aug 27, 2000 at 19:27 UTC
    Oooh.. I like that. Here's another tack at that last bit of code, that'll probably be more memory efficient in the long run:
    while (@handles) { @handles = grep { if (defined(my $line = readline($_))) { print $line; 1; } else { 0 } } @handles; }
    The advantage here is that we're rewriting @handles in one fell swoop in the fairly strongly optimized grep operation, not constantly shifting and pushing on an array that will just keep wandering through higher and higher memory. {grin}

    -- Randal L. Schwartz, Perl hacker

(jcwren) RE: (2) Merging files
by jcwren (Prior) on Aug 27, 2000 at 20:40 UTC
    Um, I tried both code samples, and tilly's worked fine, but merlyn's produces no output.

    It seems to be always hitting the 'else' clause. Changing the readline ($_) to <$_> fixes it.

    Update: jlp reports that merlyns code works for him. I'm running 5_005.03, whereas he's running 5.6.0. I don't know if that would make any difference or not.

    --Chris

    e-mail jcwren