Удалить все файлы из папки с помощью PHP?


306

Например, у меня была папка с именем «Temp», и я хотел удалить или очистить все файлы из этой папки, используя PHP. Могу ли я сделать это?


14
Хорошо, что на этот вопрос ответили ниже, прежде чем он был отмечен как дубликат. Ответы ниже намного лучше, чем связанный ответ на вопрос. Плюс вопрос другой, этот вопрос просит очистить каталог, а не удалить.
Барт Бург

1
Да, это другой вопрос, который вызвал разные ответы. Он не должен быть помечен как дубликат.
Даниэль Бингхэм

Ответы:


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

Если вы хотите удалить «скрытые» файлы, такие как .htaccess, вы должны использовать

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

4
Также есть DirectoryIterator или DirectoryRecursiveIterator.
Евгений

6
Хотя это очевидно, я бы упомянул, что, например, 'path / to / temp / *. Txt' удалит только файлы txt и так далее.
Tertium

Это также работает для относительных путей? Допустим, полный путь - «/ var / www / html / folder_and_files_to_delete /», а скрипт удаления помещен в «/var/www/html/delete_folders_and_files.php». Могу ли я просто взять "folder_and_files_to_delete" в качестве пути?
Йоано

1
@yoano да, конечно, если относительный путь правильный.
Флёрн

Можно ли использовать glob, если в каталоге находятся десятки тысяч или сотни тысяч файлов?
Дэйв Хек,

260

Если вы хотите , чтобы удалить все из папки (включая вложенные папки) использовать эту комбинацию array_map, unlinkи glob:

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

Этот вызов также может обрабатывать пустые каталоги (спасибо за подсказку, @mojuba!)


33
Лучший ответ, спасибо. Чтобы избежать уведомлений, я бы также сделал glob("...") ?: [](PHP 5.4+), потому что для пустого каталога glob()возвращается false.
Моджуба

14
Он удаляет все файлы в текущей папке, но возвращает предупреждение для подпапок и не удаляет их.
Key-Six

2
Объединение ответов Стихозы и Моджубы:array_map('unlink', ( glob( "path/to/temp/*" ) ? glob( "path/to/temp/*" ) : array() ) );
Ewout

7
@ Ewout: Даже если мы объединим ответ Стихозы и Муджубы, так как ваш запрос возвращает то же самое предупреждение для подпапок, но не удаляет их
Sulthan Allaudeen

3
К сожалению, это не удаляет вложенные папки.
tmarois

92

Вот более современный подход с использованием стандартной библиотеки PHP (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
Это прекрасно работает, когда у вас нет SSH-доступа, а FTP рекурсивно удаляет множество файлов и папок буквально часами ... с этими строками я удалил 35000 файлов менее чем за 3 секунды!
гуари

Для пользователей PHP 7.1: $ file-> getRealPath () необходимо использовать вместо $ file. В противном случае PHP выдаст вам сообщение о том, что для unlink требуется путь, а не экземпляр SplFileInfo.
KeineMaster

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

это должно быть unlink ('/ path / to / directory /'.$ fileInfo-> getFilename ()); поскольку unlink берет путь. Хороший ответ, хотя.
Вик

8
Вы даже можете сделать unlink ($ fileInfo-> getPathname ()); который даст вам полный путь к файлу. php.net/manual/en/directoryiterator.getpathname.php
Джош Холлоуэй,

Разве «DirectoryIterator» также перебирает подкаталоги? Если это так, «unlink» будет генерировать предупреждение в таких случаях. Разве тело цикла не должно больше походить на ответ Yamiko и проверять каждую запись, если это файл, перед вызовом «unlink»?
Андреас Линнерт

19

Этот код с 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);
    }
}



10

Предполагая, что у вас есть папка с МНОЖЕСТВОМ файлов, которые читают их все, а затем удаляют в два этапа, это не то, что нужно. Я считаю, что наиболее эффективный способ удаления файлов - просто использовать системную команду.

Например на Linux я использую:

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

Или это, если вы хотите рекурсивное удаление без необходимости писать рекурсивную функцию

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

точно такие же команды существуют для любой ОС, поддерживаемой PHP. Имейте в виду, что это ИСПОЛНИТЕЛЬНЫЙ способ удаления файлов. $ absolutePathToFolder ДОЛЖЕН быть проверен и защищен перед запуском этого кода, и разрешения должны быть предоставлены.


2
Немного небезопасно, используя этот метод, если $absolutePatToFolderон вообще пуст
Лоуренс Чероне

@LawrenceCherone Являются ли другие альтернативы более безопасными?
robsch

3
@LawrenceCherone Я надеюсь, что в настоящее время никто не запускает php с правами root. Серьезно, я ожидаю, что вход будет "безопасным", как и все вышеперечисленные функции.
Дарио Корно

Решения, получившие наибольшее количество голосов, не работают в средах разработки, где www или www-данные не являются собственниками. Администратор сервера должен убедиться, что установлены правильные права на папку. exec - это бесценный инструмент для достижения цели, с большой силой и т. д. stackoverflow.com/a/2765171/418974
Кристиан Бонато,

@LawrenceCherone вы совершенно правы, мой ответ был предназначен для очень конкретной ситуации, просто из соображений производительности. Модифицировал мой ответ согласно вашим заметкам.
Дарио Корно


4

Другое решение: этот класс удаляет все файлы, подкаталоги и файлы в подкаталогах.

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

Функция unlinkr рекурсивно удаляет все папки и файлы по указанному пути, следя за тем, чтобы не удалять сам скрипт.

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); 
        }
    }
}

если вы хотите удалить все файлы и папки, в которые вы помещаете этот скрипт, то назовите его следующим образом

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

если вы хотите просто удалить только php-файлы, называйте это следующим образом

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

Вы также можете использовать любой другой путь для удаления файлов

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

Это удалит все файлы в каталоге home / user / temp.


3

Опубликован класс обработки файлов и папок общего назначения для копирования, перемещения, удаления, вычисления размера и т. Д., Который может обрабатывать один файл или набор папок.

https://gist.github.com/4689551

Использовать:

Чтобы скопировать (или переместить) отдельный файл или набор папок / файлов:

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

Удалить один файл или все файлы и папки в пути:

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

Рассчитайте размер отдельного файла или набора файлов в наборе папок:

$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

Для меня решение readdirбыло лучшим и работало как шарм. При globнекоторых функциях функция не выполнялась.

// 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

Я обновил ответ @Stichoza, чтобы удалить файлы через подпапки.

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

Там есть пакет под названием "Пушех". Используя его, вы можете очистить каталог или полностью удалить каталог ( ссылка на Github ). Он также доступен на Packagist .

Например, если вы хотите очистить Tempкаталог, вы можете сделать:

Pusheh::clearDir("Temp");

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

Если вам интересно, посмотрите вики .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.