W3docs

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
ParameterDescription
$directoryPath to the directory you want to read. Can be absolute or relative to the script's working directory.
$sorting_orderHow the result is sorted: SCANDIR_SORT_ASCENDING (default, A→Z), SCANDIR_SORT_DESCENDING (Z→A), or SCANDIR_SORT_NONE (filesystem order — fastest, no sorting).
$contextAn 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

FunctionReturnsBest for
scandir()An array of all entry names at onceGetting the whole listing in one line, then filtering/sorting
glob()Full paths matching a patternPattern matching like *.jpg
opendir() + readdir()A directory handle you read one entry at a timeVery 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.

Practice

Practice
What does the scandir() function in PHP do?
What does the scandir() function in PHP do?
Was this page helpful?