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:
- Simple Interface: Returns array of all directory contents
- Cross-Platform: Works consistently across operating systems
- Building Block: Base for more complex directory operations
- 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()
andis_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!