--- name: tell signature: 'tell FILEHANDLE' signatures: - 'tell FILEHANDLE' - 'tell' since: 5.0 status: documented categories: ["I/O"] --- ```{index} single: tell; Perl built-in ``` *[I/O](../perlfunc-by-category)* # tell Return the current byte position of a filehandle. `tell` reports where the next read or write on `FILEHANDLE` will happen, measured in bytes from the start of the file. Pair it with [`seek`](seek) to save a position now and return to it later. If `FILEHANDLE` is omitted, `tell` reports the position of the handle last read from — including the implicit handle inside `while ()` loops. ## Synopsis ```perl tell FILEHANDLE tell ``` ## What you get back A non-negative integer byte offset on success, `-1` on error. The value is suitable as the `POSITION` argument to [`seek`](seek) with `WHENCE` set to `0` (absolute seek). On pipes, FIFOs, sockets, and sometimes on the standard streams, the underlying OS has no seekable position and `tell` returns `-1`; [`$!`](../perlvar) is not necessarily set in that case, so treat `-1` as the authoritative failure signal. ```perl my $pos = tell $fh; die "not a seekable handle" if $pos < 0; # ... read or write ... seek $fh, $pos, 0; # back to where we were ``` ## Global state it touches - **Last-read filehandle**: the no-argument form `tell` uses the handle most recently read from in the current scope. Every [`readline`](readline), ``, or `<>` updates this. Mixing `tell` with no argument and multiple active handles is a source of surprising results — name the handle explicitly when in doubt. - [`$!`](../perlvar) is not a reliable error channel here. Check for `-1` directly rather than testing [`$!`](../perlvar) after the call. ## Bytes, not characters `tell` always returns a **byte** offset, even when the handle has a character-oriented PerlIO layer such as `:encoding(UTF-8)` or `:utf8`. This is deliberate: translating a character count into a byte offset in a variable-width encoding would require rereading the file from the beginning. The same rule applies to [`seek`](seek) and [`sysseek`](sysseek) — they all speak bytes. Consequence: on a UTF-8 text file you cannot in general use `tell` to count characters. Use it only to mark a position you intend to feed back into [`seek`](seek). ## Examples Remember a position, read ahead, return: ```perl open my $fh, "<", "log.txt" or die $!; my $mark = tell $fh; # 0 my $first = <$fh>; # read one line seek $fh, $mark, 0; # rewind to the mark my $again = <$fh>; # same line again ``` Record the end-of-header offset so later code can rescan the body without reparsing the header: ```perl while (my $line = <$fh>) { last if $line =~ /^\r?\n\z/; # blank line ends headers } my $body_start = tell $fh; # ... process body ... seek $fh, $body_start, 0; # second pass over the body ``` The no-argument form uses the handle last read from. Inside a `while (<>)` loop that handle is the implicit `ARGV`: ```perl while (<>) { print "at ", tell, ": $_"; # offset within the current file } ``` `tell` on a pipe returns `-1` because pipes are not seekable: ```perl open my $ph, "-|", "ls" or die $!; my $pos = tell $ph; # -1 ``` Filehandles inside complex expressions need the same block form as with [`print`](print) — `tell $handles[0]` is a syntax error. Use: ```perl my @handles = (\*STDIN, $fh); my $pos = tell { $handles[1] }; ``` ## Edge cases - **Closed filehandle**: returns `-1`. Under `use warnings` a `tell() on closed filehandle` warning is emitted. - **No-argument form, nothing read yet**: returns `-1`. The "last-read filehandle" is only meaningful after an actual read. - **After `sysread` / `syswrite` / `sysseek`**: do not use `tell` on a handle you have manipulated with the `sys*` family. Those functions bypass PerlIO buffering; `tell` reports the buffered position, which will be wrong by the buffer contents. Use [`sysseek`](sysseek) with a whence of `1` and an offset of `0` as the `sys*`-safe position query. - **Standard streams**: `tell STDIN`, `tell STDOUT`, `tell STDERR` may return `-1` or a meaningful offset depending on whether the stream is backed by a regular file (shell redirection) or a terminal, pipe, or socket. - **No `systell`**: there is no separate function for buffered-bypassing position. The idiom is: ```perl my $pos = sysseek $fh, 0, 1; ``` - **Binary-mode vs text-mode on non-Linux platforms**: pperl targets Linux only, so `tell` offsets always match raw file bytes. CRLF translation layers that complicate `tell` on Windows-family perls do not apply here. - **Append mode (`>>`)**: after `open my $fh, ">>", ...`, the initial `tell $fh` may report `0` until the first write, because some platforms position the handle at end-of-file only at each write. Don't rely on the initial position; write once, then `tell`. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`seek`](seek) — jump to an absolute byte offset previously returned by `tell` - [`sysseek`](sysseek) — position query and jump for handles used with [`sysread`](sysread) / [`syswrite`](syswrite), bypassing PerlIO buffering - [`telldir`](telldir) — the directory-handle analogue; pairs with [`seekdir`](seekdir) - [`eof`](eof) — test for end-of-file rather than absolute position - [`open`](open) — produce the filehandle in the first place; mode and PerlIO layers determine whether the handle is seekable