從傳統的 opendir() 到現代 SPL 迭代器,PHP 提供多層級的目錄操作 API。本文對比效能、記憶體、易用性,助你選擇最適合的方案。
<?php
$dir = 'filelist/';
$handle = opendir($dir);
if (!$handle) die("無法開啟目錄: $dir");
echo "目錄: $dir
";
while (($entry = readdir($handle)) !== false) {
echo "$entry
";
}
closedir($handle);
?>
closedir、需自行過濾 . ..。<?php
$d = dir("/etc/php5");
echo "Handle: {$d->handle}\nPath: {$d->path}\n";
while (false !== ($entry = $d->read())) {
echo "$entry\n";
}
$d->close();
?>
opendir 的薄封裝,提供 handle、path、read()、rewind()、close()。. ..,需自行過濾。<?php
// 單層目錄
$iterator = new DirectoryIterator('filelist/');
foreach ($iterator as $fileinfo) {
if ($fileinfo->isDot()) continue; // 自動過濾 . ..
echo $fileinfo->getFilename() . "
";
// 可直接取得屬性
// $fileinfo->getSize(), ->getMTime(), ->isDir(), ->isFile(), ->getPerms()...
}
// 遞迴遍歷(含子目錄)
$recursive = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator('filelist/', RecursiveDirectoryIterator::SKIP_DOTS)
);
foreach ($recursive as $fileinfo) {
echo $fileinfo->getPathname() . " (" . ($fileinfo->isDir() ? 'DIR' : 'FILE') . ")
";
}
?>
SplFileInfo)、自動過濾 . ..、支援遞迴、可搭配 RegexIterator 過濾。<?php
// 取得所有 .php 檔案
$files = glob('filelist/*.php');
foreach ($files as $file) {
echo basename($file) . "
";
}
// 遞迴模式(PHP 5.5+ 需 GLOB_BRACE)
$files = glob('filelist/**/*.php', GLOB_BRACE);
?>
*、?、[...]、{...}。| 函數 | 用途 | 範例 |
|---|---|---|
dirname($path) | 取得目錄部分 | dirname('/a/b/c.txt') // '/a/b' |
basename($path) | 取得檔名部分 | basename('/a/b/c.txt') // 'c.txt' |
disk_free_space($path) | 剩餘空間(位元組) | disk_free_space('/') |
disk_total_space($path) | 總空間 | disk_total_space('/') |
| 場景 | 推薦方式 | 理由 |
|---|---|---|
| 簡單列出單層檔案 | DirectoryIterator | OOP 風格、自動過濾 . ..、豐富屬性 |
| 遞迴遍歷大量檔案 | RecursiveDirectoryIterator + RecursiveIteratorIterator | 記憶體效率高、可中斷、可過濾 |
| 模式匹配(如 *.log) | glob() | 語法簡潔、回傳陣列易處理 |
| 舊專案維護/極簡環境 | opendir/readdir | 無依賴、相容性最好 |
現代 PHP 專案首選 SPL 迭代器,兼具效能、記憶體效率與豐富功能。glob() 適合簡單模式匹配,opendir 僅作為底層理解或相容舊代碼。記得善用 SplFileInfo 直接取得檔案屬性,避免重複 stat 系統呼叫。