scandir()
Directory handling is an essential aspect of PHP programming. In this article, we'll take a deep dive into the PHP scandir function, which is used to read the
Introduction
Directory handling is an essential part of PHP programming — almost every backup script, file uploader, or asset processor needs to list what is inside a folder. This article takes a deep dive into the PHP scandir() function, which reads the contents of a directory in a single call. You'll learn what it returns, how to sort and filter the result, how it differs from glob(), and how to handle errors safely.
What is scandir?
scandir() reads a directory and returns the names of every entry it contains — files and subdirectories — as a flat array of strings. The array always includes the two special entries . (the current directory) and .. (the parent directory), so you almost always filter those out before using the result.
If the directory cannot be read, scandir() returns false and emits a warning. The function has been available since PHP 4.3.0 and works on both Unix-based and Windows systems.
Syntax
scandir(string $directory, int $sorting_order = SCANDIR_SORT_ASCENDING, ?resource $context = null): array|false| Parameter | Description |
|---|---|
$directory | Path to the directory you want to read. Can be absolute or relative to the script's working directory. |
$sorting_order | How the result is sorted: SCANDIR_SORT_ASCENDING (default, A→Z), SCANDIR_SORT_DESCENDING (Z→A), or SCANDIR_SORT_NONE (filesystem order — fastest, no sorting). |
$context | An optional stream context resource (rarely needed; used for custom stream wrappers). |
The function returns an array of filenames on success or false on failure.
The names are returned without the directory path. To get a usable path, prepend the directory yourself:
$directory . '/' . $entry.
How does scandir work?
In its simplest form you pass just the directory path. The contents come back sorted alphabetically (ascending) because that is the default $sorting_order. The example below filters out . and .. with array_diff() so only real entries remain:
Example of scandir() function in PHP
<?php
$dir = "/path/to/directory";
$files = scandir($dir);
// Filter out the current and parent directory entries
$filtered = array_diff($files, ['.', '..']);
foreach ($filtered as $file) {
echo $file . "<br>";
}This code displays a list of files and subdirectories in the specified directory, excluding . and ...
Sorting the directory contents
Pass a second argument to control the order of the result. The three options are:
SCANDIR_SORT_ASCENDING— alphabetical A→Z (the default).SCANDIR_SORT_DESCENDING— alphabetical Z→A.SCANDIR_SORT_NONE— no sorting; entries are returned in whatever order the filesystem provides. This is the fastest option and is worth using when you are going to sort the list yourself anyway, or when order does not matter.
For example, given a directory containing archive.txt, data.csv, report.txt, notes.md, image.png and a backups subdirectory:
How to sort scandir() output in descending order
<?php
$dir = "/path/to/directory";
$files = scandir($dir, SCANDIR_SORT_DESCENDING);
print_r($files);
// Array
// (
// [0] => report.txt
// [1] => notes.md
// [2] => image.png
// [3] => data.csv
// [4] => backups
// [5] => ..
// [6] => .
// )The same data with SCANDIR_SORT_NONE comes back unsorted (the exact order depends on the filesystem), which avoids the small overhead of sorting.
Listing only files (or only directories)
scandir() returns files and folders mixed together. To keep only files, test each entry with is_file(); to keep only directories, use is_dir(). Remember to build the full path first:
<?php
$dir = "/path/to/directory";
$entries = array_diff(scandir($dir), ['.', '..']);
$filesOnly = array_filter($entries, fn($entry) => is_file($dir . '/' . $entry));
print_r(array_values($filesOnly));
// Array
// (
// [0] => archive.txt
// [1] => data.csv
// [2] => image.png
// [3] => notes.md
// [4] => report.txt
// )Filtering by file extension
A common task is to grab only files of a given type. Combine scandir() with pathinfo() to read each entry's extension:
<?php
$dir = "/path/to/directory";
$entries = array_diff(scandir($dir), ['.', '..']);
$textFiles = array_filter(
$entries,
fn($entry) => pathinfo($entry, PATHINFO_EXTENSION) === 'txt'
);
print_r(array_values($textFiles));
// Array
// (
// [0] => archive.txt
// [1] => report.txt
// )If you only need to match files by a pattern, glob() can do this in one step — for example glob("$dir/*.txt") — and it returns full paths. Use glob() for pattern matching and scandir() when you want every entry and full control over filtering.
Handling errors
The scandir function may fail if the specified directory path is invalid or if the directory does not have the appropriate permissions. On failure, it returns false and triggers a warning. It does not throw exceptions, so you should check the return value directly. Here's an example:
Example of scandir() function in PHP with error handling
<?php
$dir = "/path/to/directory";
$files = scandir($dir);
if ($files === false) {
echo "Error: Could not read the directory.";
} else {
foreach ($files as $file) {
echo $file . "<br>";
}
}This code checks the return value of scandir() and shows an error message if the directory cannot be read. Because scandir() raises a warning (not an exception) when it fails, the strict === false check is what actually protects your code — and silencing the warning with @scandir() is discouraged, since you lose the diagnostic message.
To avoid the warning entirely, confirm the path is a readable directory before calling scandir():
<?php
$dir = "/path/to/directory";
if (is_dir($dir)) {
$files = scandir($dir);
foreach (array_diff($files, ['.', '..']) as $file) {
echo $file . "<br>";
}
} else {
echo "Error: '$dir' is not a valid directory.";
}scandir() vs other directory functions
| Function | Returns | Best for |
|---|---|---|
scandir() | An array of all entry names at once | Getting the whole listing in one line, then filtering/sorting |
glob() | Full paths matching a pattern | Pattern matching like *.jpg |
opendir() + readdir() | A directory handle you read one entry at a time | Very large directories where you don't want the whole list in memory |
For an overview of the wider toolkit, see Working with directories in PHP.
Conclusion
The scandir() function is a convenient, one-call way to read the contents of a directory in PHP. You've seen how to list entries, sort them with the three SCANDIR_SORT_* constants, keep only files or only directories, filter by extension, and handle failures safely. Reach for scandir() when you want the full listing and full control; reach for glob() when a simple pattern match will do.