Удалить все файлы из папки с помощью 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);
Floern
источник
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!)

Stichoza
источник
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;
Yamiko
источник
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());
    }
}
JakeParis
источник
это должно быть 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);
    }
}
Поэлинка Дорин
источник
16
$dir = 'your/directory/';
foreach(glob($dir.'*.*') as $v){
    unlink($v);
}
Хаим Евги
источник
11

См READDIR и Разорвать связь .

<?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);
    }
?>
StampedeXV
источник
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.

Tofeeq
источник
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');
AmyStephen
источник
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
?> 
user5579724
источник
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");

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

MAChitgarha
источник