Navigation

Php

How to Get Directory Contents with scandir()

List all files and directories efficiently using PHP's scandir() function - perfect for file browsers, cleanup scripts, and directory analysis.

Table Of Contents

Quick Answer

You can solve directory listing needs by using scandir() with proper filtering and error handling:

<?php

// Basic directory listing
$files = scandir('/path/to/directory');
if ($files === false) {
    throw new RuntimeException('Cannot read directory');
}

// Remove current and parent directory entries
$cleanFiles = array_diff($files, ['.', '..']);

// Filter only files (no directories)
function getFilesOnly(string $directory): array {
    $items = scandir($directory);
    if ($items === false) {
        return [];
    }
    
    $files = [];
    foreach ($items as $item) {
        if ($item === '.' || $item === '..') {
            continue;
        }
        
        $fullPath = $directory . DIRECTORY_SEPARATOR . $item;
        if (is_file($fullPath)) {
            $files[] = $item;
        }
    }
    
    return $files;
}

// Get directories only
function getDirectoriesOnly(string $directory): array {
    $items = scandir($directory);
    if ($items === false) {
        return [];
    }
    
    $directories = [];
    foreach ($items as $item) {
        if ($item === '.' || $item === '..') {
            continue;
        }
        
        $fullPath = $directory . DIRECTORY_SEPARATOR . $item;
        if (is_dir($fullPath)) {
            $directories[] = $item;
        }
    }
    
    return $directories;
}

// Get files with detailed information
function getDetailedDirectoryListing(string $directory): array {
    $items = scandir($directory);
    if ($items === false) {
        throw new RuntimeException("Cannot read directory: $directory");
    }
    
    $listing = [];
    
    foreach ($items as $item) {
        if ($item === '.' || $item === '..') {
            continue;
        }
        
        $fullPath = $directory . DIRECTORY_SEPARATOR . $item;
        
        $listing[] = [
            'name' => $item,
            'path' => $fullPath,
            'type' => is_dir($fullPath) ? 'directory' : 'file',
            'size' => is_file($fullPath) ? filesize($fullPath) : null,
            'modified' => filemtime($fullPath),
            'permissions' => substr(sprintf('%o', fileperms($fullPath)), -4),
            'readable' => is_readable($fullPath),
            'writable' => is_writable($fullPath)
        ];
    }
    
    return $listing;
}

// Filter files by extension
function getFilesByExtension(string $directory, array $extensions): array {
    $items = scandir($directory);
    if ($items === false) {
        return [];
    }
    
    $matchingFiles = [];
    
    foreach ($items as $item) {
        if ($item === '.' || $item === '..') {
            continue;
        }
        
        $fullPath = $directory . DIRECTORY_SEPARATOR . $item;
        if (is_file($fullPath)) {
            $extension = strtolower(pathinfo($item, PATHINFO_EXTENSION));
            if (in_array($extension, array_map('strtolower', $extensions))) {
                $matchingFiles[] = $item;
            }
        }
    }
    
    return $matchingFiles;
}

// Sort directory contents
function getSortedDirectoryContents(string $directory, string $sortBy = 'name'): array {
    $listing = getDetailedDirectoryListing($directory);
    
    usort($listing, function($a, $b) use ($sortBy) {
        switch ($sortBy) {
            case 'size':
                return ($a['size'] ?? 0) <=> ($b['size'] ?? 0);
            case 'modified':
                return $a['modified'] <=> $b['modified'];
            case 'type':
                return $a['type'] <=> $b['type'];
            case 'name':
            default:
                return strcasecmp($a['name'], $b['name']);
        }
    });
    
    return $listing;
}

// Find large files in directory
function findLargeFiles(string $directory, int $minSizeBytes = 1048576): array {
    $items = scandir($directory);
    if ($items === false) {
        return [];
    }
    
    $largeFiles = [];
    
    foreach ($items as $item) {
        if ($item === '.' || $item === '..') {
            continue;
        }
        
        $fullPath = $directory . DIRECTORY_SEPARATOR . $item;
        if (is_file($fullPath)) {
            $size = filesize($fullPath);
            if ($size >= $minSizeBytes) {
                $largeFiles[] = [
                    'name' => $item,
                    'size' => $size,
                    'size_formatted' => formatBytes($size),
                    'path' => $fullPath
                ];
            }
        }
    }
    
    // Sort by size (largest first)
    usort($largeFiles, fn($a, $b) => $b['size'] <=> $a['size']);
    
    return $largeFiles;
}

// Format bytes for human reading
function formatBytes(int $size, int $precision = 2): string {
    $units = ['B', 'KB', 'MB', 'GB', 'TB'];
    
    for ($i = 0; $size > 1024 && $i < count($units) - 1; $i++) {
        $size /= 1024;
    }
    
    return round($size, $precision) . ' ' . $units[$i];
}

// Directory statistics
function getDirectoryStats(string $directory): array {
    $items = scandir($directory);
    if ($items === false) {
        return [];
    }
    
    $stats = [
        'total_items' => 0,
        'files' => 0,
        'directories' => 0,
        'total_size' => 0,
        'largest_file' => null,
        'newest_file' => null,
        'oldest_file' => null
    ];
    
    $newestTime = 0;
    $oldestTime = PHP_INT_MAX;
    
    foreach ($items as $item) {
        if ($item === '.' || $item === '..') {
            continue;
        }
        
        $fullPath = $directory . DIRECTORY_SEPARATOR . $item;
        $stats['total_items']++;
        
        if (is_file($fullPath)) {
            $stats['files']++;
            $size = filesize($fullPath);
            $stats['total_size'] += $size;
            
            // Track largest file
            if (!$stats['largest_file'] || $size > $stats['largest_file']['size']) {
                $stats['largest_file'] = ['name' => $item, 'size' => $size];
            }
            
            // Track newest and oldest
            $mtime = filemtime($fullPath);
            if ($mtime > $newestTime) {
                $newestTime = $mtime;
                $stats['newest_file'] = ['name' => $item, 'modified' => $mtime];
            }
            if ($mtime < $oldestTime) {
                $oldestTime = $mtime;
                $stats['oldest_file'] = ['name' => $item, 'modified' => $mtime];
            }
        } else {
            $stats['directories']++;
        }
    }
    
    return $stats;
}

// Usage examples
try {
    $directory = '/path/to/scan';
    
    // Basic listing
    $allFiles = getFilesOnly($directory);
    echo "Files: " . implode(', ', $allFiles) . "\n";
    
    $directories = getDirectoriesOnly($directory);
    echo "Directories: " . implode(', ', $directories) . "\n";
    
    // Detailed listing
    $detailed = getDetailedDirectoryListing($directory);
    foreach ($detailed as $item) {
        echo "{$item['name']} ({$item['type']}) - " . 
             ($item['size'] ? formatBytes($item['size']) : 'N/A') . "\n";
    }
    
    // Filter by extension
    $images = getFilesByExtension($directory, ['jpg', 'png', 'gif']);
    echo "Image files: " . count($images) . "\n";
    
    // Sort by modification time
    $sorted = getSortedDirectoryContents($directory, 'modified');
    echo "Most recent: " . $sorted[array_key_last($sorted)]['name'] . "\n";
    
    // Find large files (over 1MB)
    $largeFiles = findLargeFiles($directory, 1048576);
    echo "Large files: " . count($largeFiles) . "\n";
    
    // Directory statistics
    $stats = getDirectoryStats($directory);
    echo "Directory contains {$stats['files']} files and {$stats['directories']} directories\n";
    echo "Total size: " . formatBytes($stats['total_size']) . "\n";
    
} catch (RuntimeException $e) {
    echo "Error: " . $e->getMessage() . "\n";
}

Explanation

scandir() provides the foundation for directory analysis:

  1. Simple Interface: Returns array of all directory contents
  2. Cross-Platform: Works consistently across operating systems
  3. Building Block: Base for more complex directory operations
  4. Efficient: Fast directory reading with minimal memory usage

Key Features:

  • Returns array of filenames including . and ..
  • Returns false on error (always check!)
  • Works with relative and absolute paths
  • Can be combined with other file functions for detailed info

Common Patterns:

  • Filter out . and .. entries
  • Combine with is_file() and is_dir() for type checking
  • Use with pathinfo() for extension filtering
  • Add file statistics for detailed analysis

Perfect for file managers, backup scripts, directory cleanup tools, and any application needing directory exploration.

Share this article

Add Comment

No comments yet. Be the first to comment!

More from Php