Read all lines in, reverse, truncate, reverse again (to set back in proper order), write out file.
#
open (LOG,"20050103.log");
seek (LOG,0,0);
@lines = reverse <LOG>; # reverse read (LIFO)
close (LOG);
#
Now you have the lines in reverse order.
Simple matter to chop off the "end" (which is the beginning) then reverse the lines again and you have truncated the biginning of the file by "X" number of lines.... write it back to disk.
Maybe someone else knows a way that less convoluted...
open( IN, $logfile );
open( OUT, ">$logFile.tmp" );
my $i = 0;
while( <IN> ) {
if( $i++ >= $xNumberOfLines ) {
my $buf;
while( 0 < read( IN, $buf ) ) {
syswrite( OUT, $buf );
}
last;
}
}
close( IN );
close( OUT );
unlink( $logFile );
rename( "$logFile.tmp", $logFile );
Note to mods: Why oh why can't we indent our code? Drives me nuts.
Me too. Not hours, but a long time.
>There's probably a unix command for it already.
No there isn't. Unix filesystem semantics simply doesn't support this use case. It can only append and remove data blocks from the the end of a file. It would be great for a lot of reasons if there were a system call for this.
Similar approaches, which of course also read the file line by line to write a new one:
If you know the number of lines to truncate: delete first 87 lines and print last section of file from line number 88:
sed '1,87d' infile > newfile
or
cat ¦ awk 'NR > 87'
If you can locate the truncate point by a regexp (a date, for example): print all lines after the first occurance of a regexp:
sed -n '/regexp/,$p'
Regards,
R.
Trim 1.0 - Removes a number of lines from the beginning of a file
[pc-tools.net...]
Also logrotate might be worth a look.