--- name: seek signature: 'seek FILEHANDLE, POSITION, WHENCE' since: 5.0 status: documented categories: ["I/O"] --- ```{index} single: seek; Perl built-in ``` *[I/O](../perlfunc-by-category)* # 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`](read), [`readline`](readline), or [`print`](print) on the handle starts from the new position. `POSITION` is a signed byte offset; `WHENCE` selects the anchor it is measured from. ## Synopsis ```perl 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 [`$!`](../perlvar) 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. ```perl 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`](../../Fcntl) for readability: - `0` / `SEEK_SET` — `POSITION` is measured from the **start of the file**. `POSITION` must be non-negative. - `1` / `SEEK_CUR` — `POSITION` is added to the **current position**. Negative values move backward, positive values forward. `seek $fh, 0, 1` is the canonical "move nowhere, but clear EOF" idiom. - `2` / `SEEK_END` — `POSITION` is added to the **end-of-file** offset. `POSITION` is typically zero or negative. ```perl 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`](tell), and the [`sysseek`](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`](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 - [`$!`](../perlvar) — 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 `FILEHANDLE` is cleared on success, even when `POSITION` and `WHENCE` leave the position unchanged. ## Examples Rewind to the start of a file before re-reading it: ```perl 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: ```perl 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: ```perl 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`](readline) retries the file for new data: ```perl while (1) { while (my $line = <$fh>) { print $line } sleep 1; seek $fh, 0, 1; # clear EOF, keep position } ``` Save a position with [`tell`](tell), read ahead, then restore: ```perl my $mark = tell $fh; my $peek = <$fh>; seek $fh, $mark, 0 or die $!; # back to where we were ``` ## Edge cases - **Unseekable handles**: pipes, sockets, `TTY`s, and most special devices return false and set [`$!`](../perlvar) to `ESPIPE` (`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 a `seek` (or [`tell`](tell), or an explicit flush) when switching direction. A WHENCE of `1` with `POSITION` of `0` is the usual no-op separator: ```perl 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 `POSITION` on filesystems that support holes; the next write fills part of the hole and the bytes in between read back as `"\0"`. - **`sysread` / `syswrite` users**: do **not** mix `seek` with [`sysread`](sysread) or [`syswrite`](syswrite). `seek` operates on the PerlIO buffer layer; the unbuffered sys-family bypasses it, so their effective positions drift apart. Use [`sysseek`](sysseek) for handles you access through the sys-family. - **Character offsets via arithmetic**: multiplying a character count by an assumed encoding width is wrong for `UTF-8` and other variable-width encodings. Use byte offsets obtained from [`tell`](tell), or read forward from a known boundary. - **Directory handles**: `seek` does not work on directory handles. Use [`seekdir`](seekdir) with a position from [`telldir`](telldir). - **Closed filehandle**: returns a false value and sets [`$!`](../perlvar); under `use warnings` a `seek() on closed filehandle` warning is emitted. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`tell`](tell) — read the current byte offset; the value round-trips safely through `seek` with `WHENCE` `0` - [`sysseek`](sysseek) — unbuffered seek for handles accessed via [`sysread`](sysread) / [`syswrite`](syswrite); use this instead of `seek` when bypassing PerlIO - [`read`](read) — buffered fixed-length read; the natural partner for positioning by byte offset - [`readline`](readline) — line-oriented read; `seek $fh, 0, 1` before a retry is the `tail -f` idiom - [`eof`](eof) — test for end-of-file; `seek` clears the EOF flag a prior read may have set - [`Fcntl`](../../Fcntl) — source of the `SEEK_SET`, `SEEK_CUR`, `SEEK_END` constants