telldir#
Return the current read position of a directory handle as an opaque token.
telldir reports where the next readdir on DIRHANDLE will
pick up. The returned value is a bookmark, not a byte offset: hand it
back to 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 on a file handle: opaque to you, meaningful only
to the matching seekdir.
Synopsis#
telldir DIRHANDLE
What you get back#
An integer on success, undef on failure (for example, if
DIRHANDLE is not an open directory handle). The integer is only
guaranteed to round-trip through seekdir on the same
open directory handle; closing and reopening the directory invalidates
every previously returned token.
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 $! on failure.
Examples#
Bookmark a position, then return to it:
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:
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 than
by remembering the token from before the first readdir:
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:
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
seekdiron the same open directory handle within the same process.Not portable across handles. Two
opendircalls 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
telldirand the matchingseekdir, 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 librarytelldir(3)/seekdir(3)pair and is not something Perl papers over. Snapshot the directory withreaddirinto a list if you need stability.Bareword vs. scalar handle.
telldir DHandtelldir $dhboth work. The bareword form is a package global; the scalar form holds a reference to an anonymous directory handle created byopendir my $dh, ....
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
seekdir— the only consumer of atelldirtoken; restoresDIRHANDLEto the bookmarked positionreaddir— the iterator whose positiontelldirreports; advances the cursor thattelldirobservesrewinddir— cheaper thanseekdirto a start-of-stream token when you just want to iterate the directory againopendir— creates theDIRHANDLEthattelldirqueries; everytelldirtoken is tied to one open callclosedir— invalidates everytelldirtoken for the handletell— the file-handle analogue; same opaque-token contract, different underlying system call