首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 檔案與目錄操作實戰:tar 壓縮/解壓與遞歸刪除非空目錄

     編輯:PHP 相關知識

前言

PHP 內建檔案系統函數功能強大,但某些系統級操作(如 tar 壓縮)仍需呼叫外部指令;而遞歸刪除非空目錄則是常見需求。本文提供兩個實用片段:system() 呼叫 tar 與自訂遞歸刪除函數 d_rmdir()。

1. 使用 tar 進行壓縮與解壓

<?php
$sourceDir = './temp';          // 要壓縮的目錄
$archive   = 'tar_test.tar.gz'; // 輸出檔名

// 壓縮:-c 建立 -z gzip -v 顯示過程 -f 指定檔名
system("tar czvf " . escapeshellarg($archive) . " " . escapeshellarg($sourceDir));

// 解壓(註解啟用):
// system("tar zxvf " . escapeshellarg($archive));
?>

關鍵點

  • escapeshellarg():必須對路徑參數轉義,防止指令注入與空白路徑錯誤。
  • 權限:PHP 執行身分(如 www-data)需對目標目錄有讀寫權限,且伺服器需安裝 tar 與 gzip。
  • 跨平台:Windows 原生無 tar,建議改用 ZipArchive 類別。

2. 遞歸刪除非空目錄:d_rmdir()

<?php
/**
 * 遞歸刪除目錄及其所有內容
 * @param string $dirname 目錄路徑
 * @return bool 成功返回 true
 */
function d_rmdir($dirname) {
    if (!is_dir($dirname)) {
        return false;
    }

    $handle = @opendir($dirname);
    if (!$handle) return false; // 權限不足等

    while (($file = @readdir($handle)) !== false) {
        if ($file === '.' || $file === '..') continue;

        $path = $dirname . '/' . $file;
        if (is_dir($path)) {
            d_rmdir($path);           // 遞歸刪除子目錄
        } else {
            @unlink($path);           // 刪除檔案
        }
    }
    closedir($handle);

    return @rmdir($dirname);          // 最後刪除空目錄本身
}

// --- 使用範例 ---
if (d_rmdir('./temp')) {
    echo 'success';
} else {
    echo 'false';
}
?>

函數設計細節

  1. @ 抑制錯誤:避免 readdir()、unlink()、rmdir() 在權限不足時拋出警告,由回傳值判斷成敗。
  2. 遞歸順序:先處理子目錄/檔案,最後刪除父目錄,符合檔案系統規則。
  3. 符號連結:is_dir() 對 symlink 返回 true,遞歸會進入連結目標;若需保留連結僅刪除連結本身,請加入 is_link($path) && unlink($path) 判斷。

現代替代方案:SPL 與 Symfony Filesystem

RecursiveDirectoryIterator (PHP 5.3+)

function deleteDirRecursive($dir) {
    $files = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::CHILD_FIRST
    );
    foreach ($files as $file) {
        $file->isDir() ? rmdir($file->getPathname()) : unlink($file->getPathname());
    }
    rmdir($dir);
}

Symfony Filesystem (企業級專案推薦)

use Symfony\Component\Filesystem\Filesystem;
$fs = new Filesystem();
$fs->remove(['./temp']); // 自動處理遞歸、權限、錯誤拋出

結語

簡單腳本可用 system('tar ...') 與自訂 d_rmdir() 快速解決問題;大型專案建議引入 ZipArchive(跨平台壓縮)與 Symfony Filesystem(健壯檔案操作),提升可維護性與安全性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved