}
If, for some odd reason, you really want to see the whole file at once
-rather than processing line by line, you can slurp it in (as long as
+rather than processing line-by-line, you can slurp it in (as long as
you can fit the whole thing in memory!):
open my $in, '<', $file or die "Can't read old file: $!"
This assumes no funny games with newline translations.
+=head2 How do I delete the last N lines from a file?
+X<lines> X<file>
+
+(contributed by brian d foy)
+
+The easiest conceptual solution is to count the lines in the
+file then start at the beginning and print the number of lines
+(minus the last N) to a new file.
+
+Most often, the real question is how you can delete the last N
+lines without making more than one pass over the file, or how to
+do it with a lot of copying. The easy concept is the hard reality when
+you might have millions of lines in your file.
+
+One trick is to use C<File::ReadBackwards>, which starts at the end of
+the file. That module provides an object that wraps the real filehandle
+to make it easy for you to move around the file. Once you get to the
+spot you need, you can get the actual filehandle and work with it as
+normal. In this case, you get the file position at the end of the last
+line you want to keep and truncate the file to that point:
+
+ use File::ReadBackwards;
+
+ my $filename = 'test.txt';
+ my $Lines_to_truncate = 2;
+
+ my $bw = File::ReadBackwards->new( $filename )
+ or die "Could not read backwards in [$filename]: $!";
+
+ my $lines_from_end = 0;
+ until( $bw->eof or $lines_from_end == $Lines_to_truncate )
+ {
+ print "Got: ", $bw->readline;
+ $lines_from_end++;
+ }
+
+ truncate( $filename, $bw->tell );
+
+The C<File::ReadBackwards> module also has the advantage of setting
+the input record separator to a regular expression.
+
+You can also use the C<Tie::File> module which lets you access
+the lines through a tied array. You can use normal array operations
+to modify your file, including setting the last index and using
+C<splice>.
+
=head2 How can I use Perl's C<-i> option from within a program?
X<-i> X<in-place>
=head2 Is there a leak/bug in glob()?
X<glob>
-Due to the current implementation on some operating systems, when you
-use the glob() function or its angle-bracket alias in a scalar
-context, you may cause a memory leak and/or unpredictable behavior. It's
-best therefore to use glob() only in list context.
+(contributed by brian d foy)
+
+Starting with Perl 5.6.0, C<glob> is implemented internally rather
+than relying on an external resource. As such, memory issues with
+C<glob> aren't a problem in modern perls.
=head2 How can I open a file with a leading ">" or trailing blanks?
X<filename, special characters>
open FILE, ">", ">file"; # filename is ">file"
=head2 How can I reliably rename a file?
-X<rename> X<mv> X<move> X<file, rename> X<ren>
+X<rename> X<mv> X<move> X<file, rename>
If your operating system supports a proper mv(1) utility or its
functional equivalent, this works:
rename($old, $new) or system("mv", $old, $new);
-It may be more portable to use the File::Copy module instead.
+It may be more portable to use the C<File::Copy> module instead.
You just copy to the new file to the new name (checking return
values), then delete the old one. This isn't really the same
-semantically as a rename(), which preserves meta-information like
+semantically as a C<rename()>, which preserves meta-information like
permissions, timestamps, inode info, etc.
-Newer versions of File::Copy export a move() function.
-
=head2 How can I lock a file?
X<lock> X<file, lock> X<flock>
=head2 How do I get a file's timestamp in perl?
X<timestamp> X<file, timestamp>
-If you want to retrieve the time at which the file was last
-read, written, or had its meta-data (owner, etc) changed,
-you use the B<-A>, B<-M>, or B<-C> file test operations as
-documented in L<perlfunc>. These retrieve the age of the
-file (measured against the start-time of your program) in
-days as a floating point number. Some platforms may not have
-all of these times. See L<perlport> for details. To
-retrieve the "raw" time in seconds since the epoch, you
-would call the stat function, then use localtime(),
-gmtime(), or POSIX::strftime() to convert this into
-human-readable form.
+If you want to retrieve the time at which the file was last read,
+written, or had its meta-data (owner, etc) changed, you use the B<-A>,
+B<-M>, or B<-C> file test operations as documented in L<perlfunc>.
+These retrieve the age of the file (measured against the start-time of
+your program) in days as a floating point number. Some platforms may
+not have all of these times. See L<perlport> for details. To retrieve
+the "raw" time in seconds since the epoch, you would call the stat
+function, then use C<localtime()>, C<gmtime()>, or
+C<POSIX::strftime()> to convert this into human-readable form.
Here's an example:
The very first thing you should do is look into getting the Term::ReadKey
extension from CPAN. As we mentioned earlier, it now even has limited
support for non-portable (read: not open systems, closed, proprietary,
-not POSIX, not Unix, etc) systems.
+not POSIX, not Unix, etc.) systems.
You should also check out the Frequently Asked Questions list in
comp.unix.* for things like this: the answer is essentially the same.