#!/usr/bin/perl
use strict;
# how many files to open? 10 in the question, 3 in examples.
my $numfh=3;
# a counter for the number of open file handles
my $openfh=$numfh;
# open an array of filehandles, one for each input file.
my @fh = ();
for my $i (1..$numfh) {
open($fh[$i],"<","file$i.txt") || die "Couldn't open file$i.txt for read: $!";
};
# open the output file.
open (my $out,">","bigfile.txt") || die "Couldn't open bigfile.txt for write: $!";
# repeat until there are no more open file handles.
until ($openfh < 1) {
for my $i (1..$numfh) {
if (eof($fh[$i])) {
# if an input file is eof, close it and decrement openfh counter.
$openfh--;
close($fh[$i]);
} else {
# print a line of input from the current input file to the output file.
print $out scalar readline $fh[$i]
};
};
}
Save this as, e.g., merge.pl
and make it executable with chmod +x merge.pl
. Then run it like so:
$ ./merge.pl
Output:
$ cat bigfile.txt
A
E
I
B
F
J
C
G
K
D
H
L
and here's a version using @ARGV and printing to STDOUT for @terdon:
#!/usr/bin/perl
use strict;
my @fh = ();
my $i=1;
for my $f (@ARGV) {
open($fh[$i++], "<", $f) || die "Couldn't open $f for read: $!";
};
my $numfh=$#fh; my $openfh=$numfh;
until ($openfh < 1) {
for my $i (1..$numfh) {
if (eof($fh[$i])) {
$openfh--;
close($fh[$i]);
} else {
print scalar readline $fh[$i]
};
};
}
Or using a hash to hold the file handles instead of an array:
#!/usr/bin/perl
use strict;
my %fh = ();
for (@ARGV) {
open($fh{$_}, "<", $_) || die "Couldn't open $_ for read: $!";
};
while (keys %fh) {
for my $f (@ARGV) {
next unless (defined($fh{$f}));
if (eof($fh{$f})) {
close($fh{$f});
delete($fh{$f});
} else {
print scalar readline $fh{$f}
};
};
}
Run either as:
$ ./merge.pl file[123].txt > bigfile.txt
The output is identical to the hard-coded version.