seek#
Reposition a filehandle for random-access reads or writes.
seek moves FILEHANDLE’s read/write pointer to a new byte offset,
mirroring the C fseek(3) call. After a successful seek, the next
read, readline, or print on the
handle starts from the new position. POSITION is a signed byte
offset; WHENCE selects the anchor it is measured from.
Synopsis#
seek FILEHANDLE, POSITION, WHENCE
seek $fh, 0, 0 # rewind to start
seek $fh, 0, 1 # no-op: clear EOF, keep position
seek $fh, -1024, 2 # 1024 bytes before EOF
What you get back#
1 on success, a false value on failure (with $! set).
Always check the return value — seeking past a short file, on an
unseekable handle (pipe, socket, TTY), or after a write error all
fail here rather than at the next read.
seek $fh, $offset, 0
or die "seek to $offset failed: $!";
WHENCE values#
WHENCE is an integer with three meaningful values. Use the symbolic
constants from Fcntl for readability:
0/SEEK_SET—POSITIONis measured from the start of the file.POSITIONmust be non-negative.1/SEEK_CUR—POSITIONis added to the current position. Negative values move backward, positive values forward.seek $fh, 0, 1is the canonical “move nowhere, but clear EOF” idiom.2/SEEK_END—POSITIONis added to the end-of-file offset.POSITIONis typically zero or negative.
use Fcntl qw(SEEK_SET SEEK_CUR SEEK_END);
seek $fh, 0, SEEK_SET; # rewind
seek $fh, 0, SEEK_END; # go to EOF (e.g. to append)
seek $fh, -$n, SEEK_CUR; # $n bytes back from here
Bytes, not characters#
Even when the handle has a character-oriented layer such as
:encoding(UTF-8), seek, tell, and the
sysseek family operate on byte offsets. A seek to
a byte offset that lands in the middle of a multi-byte sequence will
produce decoding errors or replacement characters on the next read.
If you need to position by characters, read forward from a known byte
boundary rather than trying to translate character counts to byte
offsets. tell values are safe to feed back into seek
because they were produced at byte boundaries the I/O layer already
crossed cleanly.
Global state it touches#
$!— set to the system error message on failure.The filehandle’s PerlIO buffer is discarded on success, so any data read ahead by buffering is dropped and the next read pulls fresh bytes from the underlying file.
The end-of-file flag on
FILEHANDLEis cleared on success, even whenPOSITIONandWHENCEleave the position unchanged.
Examples#
Rewind to the start of a file before re-reading it:
seek $fh, 0, 0 or die "rewind failed: $!";
while (my $line = <$fh>) { ... }
Append by positioning at end-of-file, then writing. For append-only
use, prefer opening with >> — this form is for handles already open
for read-write:
seek $fh, 0, 2 or die $!; # SEEK_END
print $fh "appended line\n";
Read a fixed-width record by index, where each record is 128 bytes:
my $record = 42;
seek $fh, $record * 128, 0 or die $!;
read $fh, my $buf, 128;
Emulate tail -f — the seek $fh, 0, 1 resets the EOF condition so
the next readline retries the file for new data:
while (1) {
while (my $line = <$fh>) { print $line }
sleep 1;
seek $fh, 0, 1; # clear EOF, keep position
}
Save a position with tell, read ahead, then restore:
my $mark = tell $fh;
my $peek = <$fh>;
seek $fh, $mark, 0 or die $!; # back to where we were
Edge cases#
Unseekable handles: pipes, sockets,
TTYs, and most special devices return false and set$!toESPIPE(Illegal seek). Check the return value; do not assume every filehandle is seekable.Mixing reads and writes on the same handle on a file opened
+<or+>requires aseek(ortell, or an explicit flush) when switching direction. A WHENCE of1withPOSITIONof0is the usual no-op separator:seek $fh, 0, 1; # allowed to switch read <-> write
Seeking past EOF on a file opened for writing is legal and creates a sparse hole up to
POSITIONon filesystems that support holes; the next write fills part of the hole and the bytes in between read back as"\0".sysread/syswriteusers: do not mixseekwithsysreadorsyswrite.seekoperates on the PerlIO buffer layer; the unbuffered sys-family bypasses it, so their effective positions drift apart. Usesysseekfor handles you access through the sys-family.Character offsets via arithmetic: multiplying a character count by an assumed encoding width is wrong for
UTF-8and other variable-width encodings. Use byte offsets obtained fromtell, or read forward from a known boundary.Directory handles:
seekdoes not work on directory handles. Useseekdirwith a position fromtelldir.Closed filehandle: returns a false value and sets
$!; underuse warningsaseek() on closed filehandlewarning is emitted.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
tell— read the current byte offset; the value round-trips safely throughseekwithWHENCE0sysseek— unbuffered seek for handles accessed viasysread/syswrite; use this instead ofseekwhen bypassing PerlIOread— buffered fixed-length read; the natural partner for positioning by byte offsetreadline— line-oriented read;seek $fh, 0, 1before a retry is thetail -fidiomeof— test for end-of-file;seekclears the EOF flag a prior read may have setFcntl— source of theSEEK_SET,SEEK_CUR,SEEK_ENDconstants