--- name: readdir signature: 'readdir DIRHANDLE' since: 5.0 status: documented categories: ["I/O"] --- ```{index} single: readdir; Perl built-in ``` *[I/O](../perlfunc-by-category)* # readdir Read the next entry, or all remaining entries, from a directory handle opened by [`opendir`](opendir). `readdir` is the directory counterpart of [`readline`](readline): it pulls names out of a directory handle one at a time in scalar context, or all at once in list context. The handle must already have been opened with [`opendir`](opendir); iteration advances a position that [`rewinddir`](rewinddir), [`seekdir`](seekdir), and [`telldir`](telldir) can manipulate. ## Synopsis ```perl readdir DIRHANDLE my $name = readdir $dh; my @names = readdir $dh; while (readdir $dh) { ... } # sets $_ ``` ## What you get back Context-dependent: - **Scalar context**: the next entry's name as a string, or [`undef`](undef) when the directory is exhausted. - **List context**: every remaining entry as a list of strings, or the empty list when the directory is already exhausted. Entries are **bare filenames**, not paths. `readdir` returns `"foo.txt"`, never `"/some/dir/foo.txt"`. If you plan to hand the result to a file test, [`open`](open), [`stat`](stat), or any other call that resolves paths against the current working directory, prepend the directory yourself — `readdir` does **not** [`chdir`](chdir) into the directory it is reading. The list always includes the entries `.` (current directory) and `..` (parent directory) as reported by the underlying filesystem. Filter them out explicitly if you do not want them: ```perl my @real = grep { $_ ne '.' && $_ ne '..' } readdir $dh; ``` **Order is filesystem-dependent**, not alphabetical. ext4, XFS, tmpfs, NFS, and FAT each return entries in their own internal order, which may be insertion order, hash order, or something else entirely. Never assume sorted output. If you need a predictable order, sort the result: ```perl my @names = sort readdir $dh; ``` ## Examples Read every name into a list, drop the dot entries, and sort: ```perl opendir(my $dh, $some_dir) or die "opendir $some_dir: $!"; my @names = sort grep { !/^\.\.?\z/ } readdir $dh; closedir $dh; ``` Iterate one entry at a time. A bare `readdir` in a `while` condition assigns to [`$_`](../perlvar) and tests the result for **definedness**, not truth — so an entry literally named `"0"` still keeps the loop running: ```perl opendir(my $dh, $some_dir) or die "opendir $some_dir: $!"; while (readdir $dh) { print "$some_dir/$_\n"; } closedir $dh; ``` Filetest with the directory prepended — forgetting the prefix is the classic `readdir` bug: ```perl opendir(my $dh, $some_dir) or die "opendir $some_dir: $!"; my @dotfiles = grep { /^\./ && -f "$some_dir/$_" } readdir $dh; closedir $dh; ``` Scalar context — one name per call, [`undef`](undef) signals end of directory: ```perl opendir(my $dh, $some_dir) or die "opendir $some_dir: $!"; while (defined(my $name = readdir $dh)) { next if $name eq '.' || $name eq '..'; process("$some_dir/$name"); } closedir $dh; ``` Rewind and read a second time — the handle stays open and usable: ```perl my @first = readdir $dh; rewinddir $dh; my @second = readdir $dh; # same entries, possibly different order ``` ## Edge cases - **Exhausted handle**: further calls return [`undef`](undef) in scalar context, empty list in list context. Use [`rewinddir`](rewinddir) to start over. - **Closed or invalid handle**: returns [`undef`](undef) (scalar) or empty list (list) and sets [`$!`](../perlvar). Under `use warnings` Perl emits `readdir() attempted on invalid dirhandle`. - **Definedness test in `while`**: both `while (readdir $dh)` and `while (my $n = readdir $dh)` (and their `for` equivalents) are special-cased to test `defined`, not truth. An entry named `"0"` is returned and the loop continues. - **`.` and `..` are always present** on POSIX filesystems, even in an otherwise empty directory. Filter them if you want only real content. - **No path prefix**: entries are bare names. Any filetest or [`open`](open) on the raw return value tests relative to the current working directory, not `$some_dir`. - **No sorting**: the order is whatever the kernel returns. Apply [`sort`](sort) explicitly if stability matters. - **Concurrent directory changes**: entries added or removed during iteration may or may not appear, per the platform. The only safe assumption is that entries present at [`opendir`](opendir) time and not removed will be reported. - **Encoding**: `readdir` returns byte strings as the kernel stores them. On a filesystem using UTF-8 filenames, apply `Encode::decode_utf8` or configure the `open` pragma if you need character strings. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`opendir`](opendir) — opens the directory handle that `readdir` reads from; always the first call in the sequence - [`closedir`](closedir) — releases the handle once iteration is done - [`rewinddir`](rewinddir) — resets the iteration position to the start of the directory - [`seekdir`](seekdir) — jumps to a previously recorded position - [`telldir`](telldir) — records the current position for later [`seekdir`](seekdir) - [`glob`](glob) — shell-style pattern matching over directory contents; higher-level when you want `*.txt` rather than every entry