						$count2 = 0;
						@fh = (_mergeFiles($opts, \@fh, _getTemp($basename, 'M', $opts)));
						print "\nCreating temp files ...\n" if $$opts{V};
					($count1, $count2, @lines) = (0, ++$count2);
					if ($count2 >= $$opts{TF}) {
					push(@fh, _writeTemp($basename, $count2, \@lines, $opts));
					}
				$count1++;
				($count1, $count2, @lines) = (0, ++$count2);
				if ($count1 >= $$opts{Y}) {
				push(@fh, _writeTemp($basename, $count2, \@lines, $opts));
				push(@lines, $line);
				}
			$$opts{T} = _tempDir($opts, $basedir) if ($filein eq ${$$opts{I}}[0]);
			$uniq = $fh{$first};
			($basename, $basedir) = fileparse($filein);
			chop($temp);
			chop($temp);
			close(F);
			if (!$$opts{O} || !@{$$opts{I}});
			if (@lines) {
			open($filein, "<$filein") || croak($!);
			open(F, "<$filein") || croak($!);
			print "Creating temp files ...\n" if $$opts{V};
			print "Sorting file $filein ...\n" if $$opts{V};
			print $file $fh{$first};
			print $file $fh{$first};
			push(@fh, $filein);
			while (defined($line=<F>)) {
			}
			}
		$$opts{I} = [$filein];
		$$opts{I} = [(ref($$opts{I}) ? @{$$opts{I}} : $$opts{I})];
		$$opts{T} .= '/' if ($$opts{T} !~ /\/$/);
		$$opts{T} .= ':' if ($$opts{T} !~ /:$/);
		$$opts{T} .= '\\' if ($$opts{T} !~ /\\$/);
		$ENV{TMPDIR} || $ENV{TMP} || $ENV{TEMP} || $basedir;
		$count1, $count2, @lines, $lines, $line, @fh, $first, $opts,
		$filein, $uniq, $basedir, $basename, %sort1, %sort2,
		$opts = \%{$_[0]};
		$temp .= $count2;
		'00'=> sub {$fh{$a} cmp $fh{$b}},
		'00'=> sub {'a'},
		'01'=> sub {$a <=> $b},
		'01'=> sub {$fh{$a} <=> $fh{$b}},
		'10'=> sub {$fh{$b} cmp $fh{$a}},
		'10'=> sub {'r'},
		'11'=> sub {$b <=> $a},
		'11'=> sub {$fh{$b} <=> $fh{$a}},
		($filein, $$opts{O}, $$opts{V}, $$opts{Y}) = @_;
		($first) = (sort sort2 keys %fh);
		*sort1 = $sort1{($$opts{R} . $$opts{N})};
		*sort2 = $sort2{($$opts{R} . $$opts{N})};
		close($_);
		croak 'Usage: sortFile($filein, $fileout [, $verbose, $chunk])';
		croak 'Usage: sortFile({I=>FILEIN, O=>FILEOUT, %otheroptions})'
		defined($line=<$first>) ? $fh{$first} = $line : delete $fh{$first};
		foreach $filein (@{$$opts{I}}) {
		foreach $filein (@{$$opts{I}}) {
		if ($$opts{U} && $uniq && $uniq ne $fh{$first}) {
		local($^W) = 0;
		print "  $_\n" if ($$opts{V});
		print $temp reverse sort @{$lines};
		print $temp sort @{$lines};
		print $temp sort sort1 @{$lines};
		unlink($_) unless ($$opts{M});
		while ($^O eq 'MacOS' && length($temp) > 31) {
		}
		}
		}
		}
		} else {
	$$lines[-1] .= $/ if ($$lines[-1] !~ m|$/$|);
	$$opts{N}	= $$opts{N} ? 1 : 0;
	$$opts{R}	= $$opts{R} ? 1 : 0;
	$$opts{TF}	||= 50;
	$$opts{T} = -d $$opts{T} ? $$opts{T} :
	$$opts{T} ||= $^O eq 'MacOS' ? 'h&hTR%f%~)' : '/tmp'; #make sure it's bad :)
	$$opts{Y}	||= 3000;
	$temp = $$opts{T} . $temp;
	%fh = map {($_ => scalar <$_>)} @$fh;
	%sort1 = (
	%sort2 = (
	($a, $b, $count1, $count2) = (1, 1, 0, 0);
	);
	);
	);
	close(_mergeFiles($opts, \@fh, $$opts{O}));
	foreach (@$fh) {
	if (!$$opts{M}) {
	if (!$_[0] && (!ref($_[0]) || !$_[1])) {
	if ($^O eq 'MacOS') {
	if (sort1() eq 'a') {
	my(
	my($basename, $count2, $lines, $opts) = @_;
	my($basename, $count2, $opts) = @_;
	my($opts, $basedir) = @_;
	my($opts, $fh, $file) = @_;
	my($temp) = $basename . '_' . time . '_' . $count2;
	my($temp) = _getTemp($basename, $count2, $opts);
	my($uniq, $first, $line);
	open($file, "+>$file") || croak($!);
	open($temp, "+>$temp") || croak($!);
	print "  $temp\n" if $$opts{V};
	print "\nCreating sorted $file ...\n" if $$opts{V};
	print "\nDeleting temp files ...\n" if ($$opts{V} && !$$opts{M});
	print "\nDone!\n\n" if $$opts{V};
	return $$opts{T};
	return $file;
	return $temp;
	return $temp;
	seek($file,0,0);
	seek($temp,0,0);
	while (-e $$opts{T} . $temp || ($^O eq 'MacOS' && length($temp) > 31)) {
	while (keys %fh) {
	{
	}
	}
	}
	}
	}
	}
	}
	}
	} else {
	} else {
	} else {
	} elsif (!ref($_[0])) {
	} elsif ($^O !~ /^VMS/i) {
	} elsif ($^O =~ /^MS(DOS|Win32)/i) {
	} elsif (sort1() eq 'r') {































































    1: 161 secs ( 0.01 usr  0.03 sys + 105.47 cusr 34.37 csys = 139.88 cpu)
    1=>q+`sort -o $ARGV[0].1 $ARGV[0]`+,
    2: 262 secs (215.18 usr 21.60 sys = 236.78 cpu)
    2=>q+open(F,$ARGV[0]);open(F1,">$ARGV[0].4");@f=<F>;print F1 sort @f+
    3: 781 secs (670.78 usr 48.45 sys = 719.23 cpu)
    3=>q+sortFile({I=>$ARGV[0],O=>"$ARGV[0].2",Y=>200000})+,
    4: 13239 secs (12981.68 usr 79.65 sys = 13061.33 cpu)
    4=>q+sortFile({I=>$ARGV[0],O=>"$ARGV[0].3"})+,
    I=>INFILE, O=>OUTFILE, V=>VERBOSE, 
    I=>[qw(file1_new file2_new)],
    M=>MERGE_ONLY, U=>UNIQUE_ONLY, 
    O=>'filex_new',
    R=>REVERSE, N=>NUMERIC, T=>TEMP_DIR
    V=>1,Y=>1000,TF=>50,M=>1,U=>1,R=>1,N=>1,T=>'/tmp'
    Y=>CHUNK, TF=>FILE_LIMIT, 
  Benchmark: timing 10 iterations of 1, 2, 3...
  sortFile('file1','file1_new',1,1000);
  sortFile(INFILE, OUTFILE [, VERBOSE, CHUNK]);
  sortFile({
  sortFile({
  timethese(10,{
  use Benchmark;
  use File::Sort qw(sortFile);
  use File::Sort qw(sortFile);
  })
  });
  });
#!perl -w
$VERSION = sprintf("%d.%02d", q$Revision: 0.11 $ =~ /(\d+)\.(\d+)/);
(thus they cannot necessarily slurp in a text file of several megabytes), 
2.5.1).  The file was a mail file around 6MB.  Note that once was with a 
=back
=cut
=head1 AUTHOR
=head1 BUGS
=head1 DESCRIPTION
=head1 EXPORT
=head1 HISTORY
=head1 NAME
=head1 RETURN VALUE
=head1 SEE ALSO
=head1 SYNOPSIS
=head1 VERSION
=item v0.01 (18 December 1997)
=item v0.02 (19 December 1997)
=item v0.03 (23 December 1997)
=item v0.10 (03 January 1998)
=item v0.11 (04 January 1998)
=over 4
@EXPORT = ();
@EXPORT_OK = qw(sortFile);
@ISA = qw(Exporter);
Added reverse and numeric sorting options.
Added unique and merge-only options.
Also, I will have the module use sort(1) if it is available.
CHUNK value of 200,000 lines, which was more than the whole file contained; 
Chris Nandor F<E<lt>pudge@pobox.comE<gt>>
Copyright (c) 1998 Chris Nandor.  All rights reserved.  This program is free
Currently, C<sortFile()> returns nothing.  Any ideas on this are welcome.
Exports C<sortFile()> on request.
File::Sort - Sort a file or merge sort multiple files.
First release.
Here are some benchmarks that might be of interest (Power Mac 7100/66 with
INFILE, but it is required.  VERBOSE is off by default.  CHUNK is how many
If MERGE_ONLY is true, then C<File::Sort> will assume the files on input are
MacPerl) do not have access to potentially infinite amounts of memory 
MkLinux DR2.1, but results were similar on an Ultra SPARC 1 running Solaris 
More cleanup; fixed special case of no linebreak on last line; wrote test 
None!  :)  I plan on making CHUNK and FILE_LIMIT more intelligent somehow, 
Note that if INFILE does not have a linebreak terminating the last line,
OS systems cannot.  So inevitably you will get much better performance with 
Perl itself.
Some cleanup; made it not subject to system file limitations; separated 
That all having been noted, there are plans to have this module use sort(1)
There are two primary syntaxes:
This time, FILEIN can be a filename or an reference to an array of filenames. 
This will sort INFILE to OUTFILE.  The OUTFILE can be the same as the
Unix systems can get away with something like that because of VM, while Mac 
Version 0.11 (03 January 1998)
WARNING Part Deux: This module is subject to change in every way, including
WARNING: This is MUCH SLOWER than using sort(1) that comes with most Unix 
__END__
a native linebreak character will be added to it.
all others.  TEMP_DIR gives a location for temporary directory.  A default
already sorted.  UNIQUE_ONLY, if true, only outputs unique lines, removing
and on allowing more ordering options besides just regular, numeric and reverse.
boxes.  This was developed primarily because some perls (specifically, 
directory of the outfile if none is given.  FILE_LIMIT is the system's limit
http://pudge.net/
if it is available.
intelligence for sort in the future.
large files on Unix than you will on Mac OS.  C'est la vie.
lines to deal with at a time (as opposed to how much memory to deal with at a
many parts out into separate functions.
module.
no strict 'refs';
nor does everyone have access to sort(1).
package File::Sort;
perl(1), sort(1).
software; you can redistribute it and/or modify it under the same terms as
sub _getTemp {
sub _mergeFiles {
sub _tempDir {
sub _writeTemp {
sub sortFile {
suite; fixed warning for redefined subs (sort1 and sort2).
the fact that it exists.
time, like sort(1); this might change).  We hope to gain some more 
to how many files can be opened at once.  A default value is given in the 
use Carp;
use Exporter;
use File::Basename;
use strict;
use vars qw(@ISA @EXPORT_OK @EXPORT $VERSION *sort1 *sort2 %fh);
will try to be ascertained if it none is given, finally reverting to the
}
}
}
}
}
