Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

mikromike's avatar

reading directory files cause out of memory.

Hello

I have one directory which has 600 000 small files on it.

    $allFiles = Storage::disk($disk)->allFiles($directory);  // this cause out of memory
    $totalFiles = count($allFiles);

It cause out of memory in Prod server.

is there any way to chuck that reading process ?

Thanks Mika.

0 likes
6 replies
LaryAI's avatar
Level 58

Hello Mika,

When dealing with a large number of files, it's important to avoid loading all the file names into memory at once. Instead, you can use a generator to iterate over the files one by one. This way, you only keep one file name in memory at a time.

Here's an example of how you can use a generator with Laravel's Filesystem to iterate over the files in a directory:

use Illuminate\Support\Facades\Storage;

function getFiles($disk, $directory) {
    $allFiles = Storage::disk($disk)->allFiles($directory);

    foreach ($allFiles as $file) {
        yield $file;
    }
}

$totalFiles = 0;
foreach (getFiles($disk, $directory) as $file) {
    $totalFiles++;
}

echo "Total number of files: " . $totalFiles;

However, the above code might still cause an out of memory error because the allFiles method is used, which attempts to load all file names into an array.

To avoid this, you can use the files method in combination with a recursive function to process one directory at a time:

use Illuminate\Support\Facades\Storage;

function countFiles($disk, $directory) {
    $totalFiles = 0;
    $directories = [ $directory ];

    while ($dir = array_shift($directories)) {
        $files = Storage::disk($disk)->files($dir);
        $totalFiles += count($files);

        // Get subdirectories to process them later
        $subdirectories = Storage::disk($disk)->directories($dir);
        $directories = array_merge($directories, $subdirectories);
    }

    return $totalFiles;
}

$totalFiles = countFiles($disk, $directory);

echo "Total number of files: " . $totalFiles;

This code will count the files without loading them all into memory at once. It processes each directory and its files separately, and then moves on to the next directory.

Remember to adjust $disk and $directory to match your actual disk and directory names. Also, ensure that you have enough memory and execution time for the script to run, as iterating over a large number of files can be time-consuming.

Snapey's avatar

scandir provides a simpler response

$count = count(scandir(Storage::disk("local")->path("public"))) - 2;

The minus 2 is to discount . and '..'

kwarnkham's avatar

I'm wondering the same thing.

Because Storage::allFiles() will give an array of files name, which can be unlimited.

How do you clean up files from s3 that are not needed in your application anymore?

For example, if I deleted a row in 'users table' and that row contains avatar column which value is the path in s3, that file is not longer needed anymore.

mikromike's avatar

@kwarnkham, Storage::allFiles() can read files from folders, that is not issue, issue is when Windows tries to do it via PHP, php cause out of memory, and crash. there is over 600k files, about 4.6G. Even File explore can not read folder without crash. I did not realised, when I put process to save Api response to small json file for same folder. Idea was read through each json file and save data db. Now I cannot read file, without filename.

Please or to participate in this conversation.