Xóa tất cả các tệp từ một thư mục bằng PHP?


306

Ví dụ, tôi có một thư mục có tên là 'Temp' và tôi muốn xóa hoặc xóa tất cả các tệp khỏi thư mục này bằng PHP. Tôi có thể làm điều này?


14
Thật tốt khi câu hỏi này đã được trả lời bên dưới trước khi nó được đánh dấu là trùng lặp. Các câu trả lời dưới đây là cách tốt hơn so với câu hỏi trả lời được liên kết. Cộng với câu hỏi là khác nhau, câu hỏi này yêu cầu làm trống một thư mục, không xóa.
Bart Burg

1
Vâng, đây là một câu hỏi khác nhau đã thu hút các câu trả lời khác nhau. Nó không nên được đánh dấu là một bản sao.
Daniel Bingham

Câu trả lời:


639
$files = glob('path/to/temp/*'); // get all file names
foreach($files as $file){ // iterate files
  if(is_file($file))
    unlink($file); // delete file
}

Nếu bạn muốn xóa các tệp 'ẩn' như .htaccess, bạn phải sử dụng

$files = glob('path/to/temp/{,.}*', GLOB_BRACE);

4
Ngoài ra còn có DirectoryIterator hoặc DirectoryRecursiveIterator.
Eugene

6
Mặc dù rõ ràng, tôi muốn đề cập rằng, ví dụ: 'path / to / temp / *. Txt' sẽ chỉ xóa các tệp txt, v.v.
Tertium

Điều này cũng hoạt động cho các đường dẫn tương đối? Vì vậy, giả sử đường dẫn đầy đủ là "/ var / www / html / folder_and_files_to_delete /" Và tập lệnh xóa được đặt trong "/var/www/html/delete_ Foldftimeand_files.php". Tôi chỉ có thể lấy "thư mục_and_files_to_delete" làm đường dẫn?
yoano

1
@yoano có chắc chắn, miễn là đường dẫn tương đối là chính xác.

Toàn cầu có ổn không khi sử dụng nếu thư mục có hàng chục nghìn hoặc hàng trăm nghìn tệp trong đó?
Dave Heq

260

Nếu bạn muốn xóa tất cả mọi thứ từ thư mục (bao gồm cả thư mục con) sử dụng sự kết hợp này của array_map, unlinkglob:

array_map( 'unlink', array_filter((array) glob("path/to/temp/*") ) );

Cuộc gọi này cũng có thể xử lý các thư mục trống (cảm ơn vì tiền boa, @mojuba!)


33
Câu trả lời tốt nhất, cảm ơn. Để tránh các thông báo tôi cũng sẽ làm glob("...") ?: [](PHP 5.4+) vì thư mục trống glob()sẽ trả về false.
mojuba

14
Nó xóa tất cả các tệp trong thư mục hiện tại, nhưng nó trả về một cảnh báo cho các thư mục con và không xóa chúng.
Key-Six

2
Kết hợp câu trả lời của Stichoza và mojuba:array_map('unlink', ( glob( "path/to/temp/*" ) ? glob( "path/to/temp/*" ) : array() ) );
Ewout

7
@Ewout: Ngay cả khi chúng tôi kết hợp câu trả lời của Stichoza và Moujuba khi bạn đưa ra cảnh báo tương tự cho các thư mục con và nó sẽ không xóa chúng
Sulthan Allaudeen

3
Thật không may, điều này không xóa các thư mục con.
tmarois

92

Đây là một cách tiếp cận hiện đại hơn bằng cách sử dụng Thư viện PHP tiêu chuẩn (SPL) .

$dir = "path/to/directory";
$di = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS);
$ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::CHILD_FIRST);
foreach ( $ri as $file ) {
    $file->isDir() ?  rmdir($file) : unlink($file);
}
return true;

1
Điều này hoạt động tốt, khi bạn không có quyền truy cập SSH và FTP mất hàng giờ đồng hồ để xóa đệ quy rất nhiều tệp và thư mục ... với những dòng đó tôi đã xóa 35000 tệp trong chưa đầy 3 giây!
guari

Đối với người dùng PHP 7.1: $ file-> getRealPath () phải được sử dụng thay vì $ file. Mặt khác, PHP sẽ cung cấp cho bạn một lỗi nói rằng hủy liên kết yêu cầu một đường dẫn, không phải là một thể hiện của SplFileInfo.
KeineMaster

68
foreach (new DirectoryIterator('/path/to/directory') as $fileInfo) {
    if(!$fileInfo->isDot()) {
        unlink($fileInfo->getPathname());
    }
}

nó nên được bỏ liên kết ('/ path / to / thư mục /'.$ fileInfo-> getFilename ()); kể từ khi unlink mất trong đường dẫn. Câu trả lời tốt mặc dù.
Vic

8
Bạn thậm chí có thể hủy liên kết ($ fileInfo-> getPathname ()); mà sẽ cung cấp cho bạn đường dẫn đầy đủ đến tập tin. php.net/manual/en/directoryiterator.getpathname.php
Josh Holloway

Không phải 'DirectoryIterator' cũng lặp đi lặp lại trên các thư mục con? Nếu vậy 'hủy liên kết' sẽ tạo ra một cảnh báo trong những trường hợp như vậy. Không phải phần thân của vòng lặp trông giống như trong câu trả lời của Yamiko hơn và kiểm tra từng mục nếu đó là một tệp trước khi gọi 'hủy liên kết'?
Andreas Linnert

19

Mã này từ http://php.net/unlink :

/**
 * Delete a file or recursively delete a directory
 *
 * @param string $str Path to file or directory
 */
function recursiveDelete($str) {
    if (is_file($str)) {
        return @unlink($str);
    }
    elseif (is_dir($str)) {
        $scan = glob(rtrim($str,'/').'/*');
        foreach($scan as $index=>$path) {
            recursiveDelete($path);
        }
        return @rmdir($str);
    }
}

16
$dir = 'your/directory/';
foreach(glob($dir.'*.*') as $v){
    unlink($v);
}

11

Xem readdirbỏ liên kết .

<?php
    if ($handle = opendir('/path/to/files'))
    {
        echo "Directory handle: $handle\n";
        echo "Files:\n";

        while (false !== ($file = readdir($handle)))
        {
            if( is_file($file) )
            {
                unlink($file);
            }
        }
        closedir($handle);
    }
?>

10

Giả sử bạn có một thư mục có RẤT NHIỀU tệp đọc tất cả và sau đó xóa theo hai bước thì không hiệu quả. Tôi tin rằng cách hiệu quả nhất để xóa các tập tin là chỉ sử dụng một lệnh hệ thống.

Ví dụ trên linux tôi sử dụng:

exec('rm -f '. $absolutePathToFolder .'*');

Hoặc điều này nếu bạn muốn xóa đệ quy mà không cần phải viết hàm đệ quy

exec('rm -f -r '. $absolutePathToFolder .'*');

các lệnh chính xác tương tự tồn tại cho bất kỳ HĐH nào được PHP hỗ trợ. Hãy ghi nhớ đây là cách xóa tệp. $ perfectPathToFolder PHẢI được kiểm tra và bảo mật trước khi chạy mã này và phải cấp quyền.


2
Bit không an toàn khi sử dụng phương pháp này, nếu $absolutePatToFolderđã hết
Lawrence Cherone

@LawrenceCherone Các lựa chọn thay thế khác có an toàn hơn không?
robsch

3
@LawrenceCherone Tôi hy vọng không có ai chạy php với quyền root hiện nay. Nghiêm túc, tôi hy vọng đầu vào là "an toàn", vì tất cả các chức năng trên.
Dario Corno

Các giải pháp được bình chọn nhiều nhất không hoạt động trong môi trường dev nơi dữ liệu www hoặc www không phải là chủ sở hữu. Tùy thuộc vào quản trị viên máy chủ để đảm bảo quyền thích hợp của thư mục được đặt. exec là một công cụ vô giá để hoàn thành công việc và với sức mạnh lớn, v.v. stackoverflow.com/a/2765171/418974
Christian Bonato

@LawrenceCherone bạn hoàn toàn chính xác câu trả lời của tôi có nghĩa là cho một tình huống rất cụ thể, chỉ vì lý do hiệu suất. Sửa đổi câu trả lời của tôi theo ghi chú của bạn.
Dario Corno


4

Một giải pháp khác: Lớp này xóa tất cả các tệp, thư mục con và tệp trong thư mục con.

class Your_Class_Name {
    /**
     * @see http://php.net/manual/de/function.array-map.php
     * @see http://www.php.net/manual/en/function.rmdir.php 
     * @see http://www.php.net/manual/en/function.glob.php
     * @see http://php.net/manual/de/function.unlink.php
     * @param string $path
     */
    public function delete($path) {
        if (is_dir($path)) {
            array_map(function($value) {
                $this->delete($value);
                rmdir($value);
            },glob($path . '/*', GLOB_ONLYDIR));
            array_map('unlink', glob($path."/*"));
        }
    }
}

4

Hàm unlinkr xóa đệ quy tất cả các thư mục và tệp trong đường dẫn đã cho bằng cách đảm bảo rằng nó không xóa chính tập lệnh.

function unlinkr($dir, $pattern = "*") {
    // find all files and folders matching pattern
    $files = glob($dir . "/$pattern"); 

    //interate thorugh the files and folders
    foreach($files as $file){ 
    //if it is a directory then re-call unlinkr function to delete files inside this directory     
        if (is_dir($file) and !in_array($file, array('..', '.')))  {
            echo "<p>opening directory $file </p>";
            unlinkr($file, $pattern);
            //remove the directory itself
            echo "<p> deleting directory $file </p>";
            rmdir($file);
        } else if(is_file($file) and ($file != __FILE__)) {
            // make sure you don't delete the current script
            echo "<p>deleting file $file </p>";
            unlink($file); 
        }
    }
}

Nếu bạn muốn xóa tất cả các tệp và thư mục nơi bạn đặt tập lệnh này, hãy gọi nó như sau

//get current working directory
$dir = getcwd();
unlinkr($dir);

Nếu bạn chỉ muốn xóa các tập tin php thì hãy gọi nó như sau

unlinkr($dir, "*.php");

bạn cũng có thể sử dụng bất kỳ đường dẫn nào khác để xóa các tập tin

unlinkr("/home/user/temp");

Điều này sẽ xóa tất cả các tập tin trong thư mục home / user / temp.


3

Đã đăng một lớp mục đích chung và lớp xử lý thư mục để sao chép, di chuyển, xóa, tính toán kích thước, v.v., có thể xử lý một tệp hoặc một tập hợp các thư mục.

https://gist.github.com/4689551

Để sử dụng:

Để sao chép (hoặc di chuyển) một tệp hoặc một tập hợp các thư mục / tệp:

$files = new Files();
$results = $files->copyOrMove('source/folder/optional-file', 'target/path', 'target-file-name-for-single-file.only', 'copy');

Xóa một tệp hoặc tất cả các tệp và thư mục trong một đường dẫn:

$files = new Files();
$results = $files->delete('source/folder/optional-file.name');

Tính kích thước của một tệp hoặc một tập hợp tệp trong một tập hợp các thư mục:

$files = new Files();
$results = $files->calculateSize('source/folder/optional-file.name');

1
 <?
//delete all files from folder  & sub folders
function listFolderFiles($dir)
{
    $ffs = scandir($dir);
    echo '<ol>';
    foreach ($ffs as $ff) {
        if ($ff != '.' && $ff != '..') {
            if (file_exists("$dir/$ff")) {
                unlink("$dir/$ff");
            }
            echo '<li>' . $ff;
            if (is_dir($dir . '/' . $ff)) {
                listFolderFiles($dir . '/' . $ff);
            }
            echo '</li>';
        }
    }
    echo '</ol>';
}
$arr = array(
    "folder1",
    "folder2"
);
for ($x = 0; $x < count($arr); $x++) {
    $mm = $arr[$x];
    listFolderFiles($mm);
}
//end
?> 

1

Đối với tôi, giải pháp readdirtốt nhất và hoạt động như một cơ duyên. Với glob, chức năng đã thất bại với một số tình huống.

// Remove a directory recursively
function removeDirectory($dirPath) {
    if (! is_dir($dirPath)) {
        return false;
    }

    if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') {
        $dirPath .= '/';
    }

    if ($handle = opendir($dirPath)) {

        while (false !== ($sub = readdir($handle))) {
            if ($sub != "." && $sub != ".." && $sub != "Thumb.db") {
                $file = $dirPath . $sub;

                if (is_dir($file)) {
                    removeDirectory($file);
                } else {
                    unlink($file);
                }
            }
        }

        closedir($handle);
    }

    rmdir($dirPath);
}

0

Tôi đã cập nhật câu trả lời của @Stichoza để xóa các tệp thông qua các thư mục con.

function glob_recursive($pattern, $flags = 0) {
    $fileList = glob($pattern, $flags);
    foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) {
        $subPattern = $dir.'/'.basename($pattern);
        $subFileList = glob_recursive($subPattern, $flags);
        $fileList = array_merge($fileList, $subFileList);
    }
    return $fileList;
}

function glob_recursive_unlink($pattern, $flags = 0) {
    array_map('unlink', glob_recursive($pattern, $flags));
}

0
public static function recursiveDelete($dir)
{
    foreach (new \DirectoryIterator($dir) as $fileInfo) {
        if (!$fileInfo->isDot()) {
            if ($fileInfo->isDir()) {
                recursiveDelete($fileInfo->getPathname());
            } else {
                unlink($fileInfo->getPathname());
            }
        }
    }
    rmdir($dir);
}

0

Có một gói gọi là "Pusheh". Sử dụng nó, bạn có thể xóa một thư mục hoặc xóa hoàn toàn một thư mục ( liên kết Github ). Nó cũng có sẵn trên Packagist .

Chẳng hạn, nếu bạn muốn xóa Tempthư mục, bạn có thể làm:

Pusheh::clearDir("Temp");

// Or you can remove the directory completely
Pusheh::removeDirRecursively("Temp");

Nếu bạn quan tâm, hãy xem wiki .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.