--- name: telldir signature: 'telldir DIRHANDLE' since: 5.0 status: documented categories: ["I/O"] --- ```{index} single: telldir; Perl built-in ``` *[I/O](../perlfunc-by-category)* # telldir Return the current read position of a directory handle as an opaque token. `telldir` reports where the next [`readdir`](readdir) on `DIRHANDLE` will pick up. The returned value is a bookmark, not a byte offset: hand it back to [`seekdir`](seekdir) to resume iteration at the same entry, or discard it. The number has no arithmetic meaning — it is not an index into the directory, not a count of entries read, and not comparable across directory handles. Treat it the way you would treat the return value of [`tell`](tell) on a file handle: opaque to you, meaningful only to the matching [`seekdir`](seekdir). ## Synopsis ```perl telldir DIRHANDLE ``` ## What you get back An integer on success, [`undef`](undef) on failure (for example, if `DIRHANDLE` is not an open directory handle). The integer is only guaranteed to round-trip through [`seekdir`](seekdir) on the **same** open directory handle; closing and reopening the directory invalidates every previously returned token. ```perl opendir my $dh, $path or die "opendir $path: $!"; my $pos = telldir $dh; # ... readdir a few entries ... seekdir $dh, $pos; # back to where $pos was taken ``` ## Global state it touches Sets [`$!`](../perlvar) on failure. ## Examples Bookmark a position, then return to it: ```perl opendir my $dh, "." or die "opendir: $!"; readdir $dh; # consume "." my $mark = telldir $dh; my @rest = readdir $dh; # drain the rest seekdir $dh, $mark; my @again = readdir $dh; # same entries as @rest closedir $dh; ``` Record a token before each entry so you can rewind one step: ```perl opendir my $dh, $path or die "opendir $path: $!"; my $prev; while (defined(my $entry = readdir $dh)) { last if $entry eq "STOP"; $prev = telldir $dh; # position *after* the current entry } seekdir $dh, $prev if defined $prev; ``` Rewinding to the start is better done with [`rewinddir`](rewinddir) than by remembering the token from before the first [`readdir`](readdir): ```perl opendir my $dh, $path or die "opendir $path: $!"; my @first_pass = readdir $dh; rewinddir $dh; # cleaner than seekdir $dh, $start_token my @second_pass = readdir $dh; ``` Check for failure explicitly when the handle might be closed: ```perl my $pos = telldir $dh; defined $pos or die "telldir failed: $!"; ``` ## Edge cases - **Token is opaque.** Do not compare, add, subtract, or persist the value. It is valid only for [`seekdir`](seekdir) on the same open directory handle within the same process. - **Not portable across handles.** Two `opendir` calls on the same directory produce independent handles; a token from one is meaningless to the other. - **Not stable across `closedir` / `opendir`.** Reopening the directory starts a fresh iteration; old tokens no longer refer to anything. - **Directory compaction.** If the underlying filesystem or another process modifies the directory (adds, removes, or renames entries) between `telldir` and the matching [`seekdir`](seekdir), the resumed position may skip entries, repeat entries, or land on a different entry than the one originally bookmarked. This is a property of the C library `telldir(3)` / `seekdir(3)` pair and is not something Perl papers over. Snapshot the directory with [`readdir`](readdir) into a list if you need stability. - **Closed or never-opened handle.** Returns [`undef`](undef) and sets [`$!`](../perlvar). - **Bareword vs. scalar handle.** `telldir DH` and `telldir $dh` both work. The bareword form is a package global; the scalar form holds a reference to an anonymous directory handle created by `opendir my $dh, ...`. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`seekdir`](seekdir) — the only consumer of a `telldir` token; restores `DIRHANDLE` to the bookmarked position - [`readdir`](readdir) — the iterator whose position `telldir` reports; advances the cursor that `telldir` observes - [`rewinddir`](rewinddir) — cheaper than `seekdir` to a start-of-stream token when you just want to iterate the directory again - [`opendir`](opendir) — creates the `DIRHANDLE` that `telldir` queries; every `telldir` token is tied to one open call - [`closedir`](closedir) — invalidates every `telldir` token for the handle - [`tell`](tell) — the file-handle analogue; same opaque-token contract, different underlying system call