PHP 提供豐富的檔案系統函數,涵蓋路徑解析、目錄遍歷、檔案讀寫、權限管理等核心功能。本文系統整理常用函數並提供最佳實踐範例。
string basename ( string $path [, string $suffix ] )
$suffix 參數移除副檔名/ 與 \ 雙分隔符echo basename('/var/www/index.php'); // index.php
echo basename('/var/www/index.php', '.php'); // index
string dirname ( string $path )
echo dirname('/var/www/index.php'); // /var/www
array pathinfo ( string $path [, int $options = PATHINFO_DIRNAME | PATHINFO_BASENAME | PATHINFO_EXTENSION | PATHINFO_FILENAME ] )
$info = pathinfo('/var/www/image.png');
/*
Array
(
[dirname] => /var/www
[basename] => image.png
[extension] => png
[filename] => image
)
*/
// 只取特定資訊
echo pathinfo($path, PATHINFO_EXTENSION); // png
string|false realpath ( string $path )
./、../、多餘斜線falseecho realpath('../public/./assets/../css/style.css');
// /var/www/html/css/style.css
bool is_dir ( string $filename )
注意: 結果會被快取,需搭配 clearstatcache() 使用。
$handle = opendir('/var/www/html');
if ($handle) {
while (($entry = readdir($handle)) !== false) {
if ($entry !== '.' && $entry !== '..') {
echo $entry . PHP_EOL;
}
}
closedir($handle);
}
array|false glob ( string $pattern [, int $flags = 0 ] )
常用旗標:
GLOB_BRACE:支援 {a,b,c} 多模式GLOB_ONLYDIR:僅回傳目錄GLOB_NOSORT:不排序,效能較好// 找所有 PHP 與 JS 檔
$files = glob('*.{php,js}', GLOB_BRACE);
// 遞迴搜尋 (需自行實作)
function globRecursive($pattern, $flags = 0) {
$files = glob($pattern, $flags);
foreach (glob(dirname($pattern) . '/*', GLOB_ONLYDIR | GLOB_NOSORT) as $dir) {
$files = array_merge($files, globRecursive($dir . '/' . basename($pattern), $flags));
}
return $files;
}
// 傳統寫法
$fp = fopen('data.txt', 'w');
fwrite($fp, '內容');
fclose($fp);
// PHP 5.4+ 簡潔寫法
file_put_contents('data.txt', '內容');
// 追加模式
file_put_contents('log.txt', "新行\n", FILE_APPEND | LOCK_EX);
// 全部讀入字串
$content = file_get_contents('data.txt');
// 逐行讀入陣列
$lines = file('data.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
// 大檔案串流處理
$fp = fopen('huge.log', 'r');
while (($line = fgets($fp)) !== false) {
// 處理單行
}
fclose($fp);
unlink('temp.txt'); // 回傳 bool
rename('old.txt', 'new.txt'); // 同目錄重命名
rename('a/file.txt', 'b/file.txt'); // 移動並重命名
// 目標目錄必須存在
copy('source.txt', 'dest.txt'); // 無法複製目錄
file_exists('path'); // 檔案/目錄是否存在
is_file('path'); // 是否為檔案
is_readable('path'); // 是否可讀
is_writable('path'); // 是否可寫
filesize('path'); // 檔案大小 (bytes)
filemtime('path'); // 最後修改時間 (timestamp)
filectime('path'); // 最後狀態變更時間
fileatime('path'); // 最後存取時間
// 建立目錄 (遞迴模式)
mkdir('path/to/dir', 0755, true);
// 刪除空目錄
rmdir('empty_dir');
// 遞迴刪除非空目錄
function removeDirRecursive($dir) {
$items = glob($dir . '/*');
foreach ($items as $item) {
is_dir($item) ? removeDirRecursive($item) : unlink($item);
}
rmdir($dir);
}
class FileSystem {
// 取得目錄大小
public static function getDirSize($dir) {
$size = 0;
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)) as $file) {
if ($file->isFile()) $size += $file->getSize();
}
return $size;
}
// 格式化位元組
public static function formatBytes($bytes, $precision = 2) {
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
return round($bytes / (1024 ** $pow), $precision) . ' ' . $units[$pow];
}
// 安全刪除 (支援檔案/目錄)
public static function delete($path) {
if (is_file($path) || is_link($path)) {
return unlink($path);
}
if (is_dir($path)) {
$items = array_diff(scandir($path), ['.', '..']);
foreach ($items as $item) {
self::delete($path . DIRECTORY_SEPARATOR . $item);
}
return rmdir($path);
}
return false;
}
}
DIRECTORY_SEPARATOR 或 / (PHP 自動轉換)@ 抑制警告並自行判斷回傳值fopen/fgets),避免記憶體耗盡LOCK_EX,讀取時考慮 LOCK_SHrealpath() 驗證路徑在允許目錄內