seekdir#
Restore a directory handle to a position previously captured by telldir.
seekdir moves the read cursor of DIRHANDLE to POS, so that the
next readdir call returns the entry that would have been
returned when POS was first obtained from telldir on the
same handle. It is the directory counterpart of 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 earlier.
Synopsis#
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 $! 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:
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 on conforming systems, but
rewinddir is the idiomatic spelling for that intent:
seekdir $dh, 0; # works, but say what you mean:
rewinddir $dh; # clearer
Edge cases#
POSmust come fromtelldiron 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 nextreaddir, skip entries, or return duplicates.Directory compaction between
telldirandseekdir: 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), thePOScookie may no longer refer to the same entry — or to any entry at all. This is a property of the underlyingseekdir(3)and is not a pperl limitation. For stable iteration over a changing directory, snapshot the list withreaddirin list context and work off the copy.Unopened or closed handle: sets
$!. Underuse warningsyou get aseekdir() attempted on invalid dirhandlewarning. Nothing in the return value tells you this happened — check$!or usedefined fileno($dh)/ explicit bookkeeping if you need to guard.Not a byte offset:
POSis an opaque token. Arithmetic on it (seekdir $dh, $pos + 1) is meaningless; the only safe values are0(start of directory, and even then preferrewinddir) and values returned bytelldir.Entry order is unspecified:
seekdirreplays whatever order the kernel originally returned. That order is not sorted, not alphabetical, and not guaranteed to match a freshopendirof 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 ofseek’s whence argument.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
telldir— produce thePOScookie thatseekdirconsumes; the two are only useful as a pairreaddir— read the next entry; resumes from the positionseekdirjust setrewinddir— the idiomatic way to return to the start of a directory; prefer it overseekdir $dh, 0opendir— open the directory and obtain the handleseekdiroperates onseek— the file-handle analogue, but with a true byte offset and awhenceargument; directory handles have neither