--- name: seekdir signature: 'seekdir DIRHANDLE,POS' since: 5.0 status: documented categories: ["I/O"] --- ```{index} single: seekdir; Perl built-in ``` *[I/O](../perlfunc-by-category)* # seekdir Restore a directory handle to a position previously captured by [`telldir`](telldir). `seekdir` moves the read cursor of `DIRHANDLE` to `POS`, so that the next [`readdir`](readdir) call returns the entry that would have been returned when `POS` was first obtained from [`telldir`](telldir) on the same handle. It is the directory counterpart of [`seek`](seek) on a file handle — with the crucial restriction that `POS` is not a byte offset you can compute, it is an opaque cookie you must have taken from [`telldir`](telldir) earlier. ## Synopsis ```perl seekdir DIRHANDLE, POS ``` ## What you get back No meaningful value. `seekdir` returns what the underlying `seekdir(3)` returns, which on Linux is nothing useful — do **not** branch on the return value. To detect trouble, check [`$!`](../perlvar) after the call, or verify that the handle is still open before calling. ## Typical use You are walking a directory, notice an entry you want to revisit later, and remember where you were so you can return to it after reading on: ```perl opendir my $dh, $path or die "opendir $path: $!"; my %bookmarks; while (my $entry = readdir $dh) { $bookmarks{$entry} = telldir $dh # position AFTER reading $entry if $entry =~ /\.conf\z/; } # later: re-read the entry that follows the first .conf file seekdir $dh, $bookmarks{(sort keys %bookmarks)[0]}; my $next = readdir $dh; closedir $dh; ``` Returning to the start is the common special case — a `seekdir $dh, 0` call is equivalent to [`rewinddir`](rewinddir) on conforming systems, but [`rewinddir`](rewinddir) is the idiomatic spelling for that intent: ```perl seekdir $dh, 0; # works, but say what you mean: rewinddir $dh; # clearer ``` ## Edge cases - **`POS` must come from [`telldir`](telldir) on the same handle.** Passing an integer you made up, a value from a different handle, or a stale value from a handle that has since been closed and re-opened is undefined behaviour. The kernel may accept it silently and hand you garbage on the next [`readdir`](readdir), skip entries, or return duplicates. - **Directory compaction between [`telldir`](telldir) and `seekdir`**: if the filesystem has compacted or reorganised the directory between the two calls (files created, deleted, or renamed in the same directory by any process), the `POS` cookie may no longer refer to the same entry — or to any entry at all. This is a property of the underlying `seekdir(3)` and is not a pperl limitation. For stable iteration over a changing directory, snapshot the list with [`readdir`](readdir) in list context and work off the copy. - **Unopened or closed handle**: sets [`$!`](../perlvar). Under `use warnings` you get a `seekdir() attempted on invalid dirhandle` warning. Nothing in the return value tells you this happened — check [`$!`](../perlvar) or use `defined fileno($dh)` / explicit bookkeeping if you need to guard. - **Not a byte offset**: `POS` is an opaque token. Arithmetic on it (`seekdir $dh, $pos + 1`) is meaningless; the only safe values are `0` (start of directory, and even then prefer [`rewinddir`](rewinddir)) and values returned by [`telldir`](telldir). - **Entry order is unspecified**: `seekdir` replays whatever order the kernel originally returned. That order is not sorted, not alphabetical, and not guaranteed to match a fresh [`opendir`](opendir) of the same path later. If your code sorts, sort explicitly each time. - **`SEEK_CUR`-style relative seeks do not exist** for directory handles. There is no equivalent of [`seek`](seek)'s whence argument. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`telldir`](telldir) — produce the `POS` cookie that `seekdir` consumes; the two are only useful as a pair - [`readdir`](readdir) — read the next entry; resumes from the position `seekdir` just set - [`rewinddir`](rewinddir) — the idiomatic way to return to the start of a directory; prefer it over `seekdir $dh, 0` - [`opendir`](opendir) — open the directory and obtain the handle `seekdir` operates on - [`seek`](seek) — the file-handle analogue, but with a true byte offset and a `whence` argument; directory handles have neither