Как я могу заставить этот скрипт удалить папку, которая находится внутри папки [duplicate]

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

Если мы посмотрим на широко предложенное регулярное выражение для этого вопроса:

.*[^a]$

Мы будем что он почти работает. Он не принимает пустую строку, которая может быть немного неудобной. Однако это небольшая проблема при работе с одним персонажем. Однако, если мы хотим исключить целую строку, например. "abc", то:

.*[^a][^b][^c]$

не будет работать. Например, он не принимает ac.

Однако для решения этой проблемы существует простое решение. Мы можем просто сказать:

.{,2}$|.*[^a][^b][^c]$

или более обобщенная версия:

.{,n-1}$|.*[^firstchar][^secondchar]$ где n - длина строки, которую вы хотите запретить (для abc это 3), а firstchar, secondchar, ... являются первыми, вторыми ... n-ыми символами вашей строки (для abc это будет a, затем b, затем c).

Это происходит из простого наблюдения, что строка, которая короче текста, которую мы не запретим, не может содержать этот текст по определению. Таким образом, мы можем либо принять все, что короче («ab» не «abc»), либо что-то достаточно длинное для нас, но без конца.

Вот пример поиска, который удалит все файлы, которые не являются .jpg:

find . -regex '.{,3}$|.*[^.][^j][^p][^g]$' -delete

182
задан Nick 21 November 2012 в 23:17
поделиться

29 ответов

В настоящее время доступно как минимум два варианта.

  1. Перед удалением папки удалите все ее файлы и папки (а это означает рекурсию!). Вот пример:
    public static function deleteDir($dirPath) {
        if (! is_dir($dirPath)) {
            throw new InvalidArgumentException("$dirPath must be a directory");
        }
        if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') {
            $dirPath .= '/';
        }
        $files = glob($dirPath . '*', GLOB_MARK);
        foreach ($files as $file) {
            if (is_dir($file)) {
                self::deleteDir($file);
            } else {
                unlink($file);
            }
        }
        rmdir($dirPath);
    }
    
  2. И если вы используете 5.2+, вы можете использовать RecursiveIterator для этого, не требуя самой рекурсии:
    $dir = 'samples' . DIRECTORY_SEPARATOR . 'sampledirtree';
    $it = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS);
    $files = new RecursiveIteratorIterator($it,
                 RecursiveIteratorIterator::CHILD_FIRST);
    foreach($files as $file) {
        if ($file->isDir()){
            rmdir($file->getRealPath());
        } else {
            unlink($file->getRealPath());
        }
    }
    rmdir($dir);
    
290
ответ дан deefour 31 August 2018 в 10:30
поделиться

Как насчет этого:

function recursiveDelete($dirPath, $deleteParent = true){
    foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dirPath, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST) as $path) {
        $path->isFile() ? unlink($path->getPathname()) : rmdir($path->getPathname());
    }
    if($deleteParent) rmdir($dirPath);
}
3
ответ дан adrian 31 August 2018 в 10:30
поделиться

Использование DirectoryIterator эквивалентно предыдущему ответу ...

function deleteFolder($rootPath)
{   
    foreach(new DirectoryIterator($rootPath) as $fileToDelete)
    {
        if($fileToDelete->isDot()) continue;
        if ($fileToDelete->isFile())
            unlink($fileToDelete->getPathName());
        if ($fileToDelete->isDir())
            deleteFolder($fileToDelete->getPathName());
    }

    rmdir($rootPath);
}
1
ответ дан Alan Trewartha 31 August 2018 в 10:30
поделиться

Вот простое решение

$dirname = $_POST['d'];
    $folder_handler = dir($dirname);
    while ($file = $folder_handler->read()) {
        if ($file == "." || $file == "..")
            continue;
        unlink($dirname.'/'.$file);

    }
   $folder_handler->close();
   rmdir($dirname);
-2
ответ дан Andy Obusek 31 August 2018 в 10:30
поделиться

Короткая функция, выполняющая задание:

function deleteDir($path) {
    return is_file($path) ?
            @unlink($path) :
            array_map(__FUNCTION__, glob($path.'/*')) == @rmdir($path);
}

Я использую его в классе Utils следующим образом:

class Utils {
    public static function deleteDir($path) {
        $class_func = array(__CLASS__, __FUNCTION__);
        return is_file($path) ?
                @unlink($path) :
                array_map($class_func, glob($path.'/*')) == @rmdir($path);
    }
}

С большой силой приходит большая ответственность: Когда вы вызываете эту функцию с пустым значением, она удаляет файлы, начиная с root (/). В качестве защиты вы можете проверить, пуст ли пуст:

function deleteDir($path) {
    if (empty($path)) { 
        return false;
    }
    return is_file($path) ?
            @unlink($path) :
            array_map(__FUNCTION__, glob($path.'/*')) == @rmdir($path);
}
44
ответ дан Blaise 31 August 2018 в 10:30
поделиться

Функция Glob не возвращает скрытые файлы, поэтому scandir может быть более полезным при попытке удалить рекурсивно дерево.

<?php
public static function delTree($dir) {
   $files = array_diff(scandir($dir), array('.','..'));
    foreach ($files as $file) {
      (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file");
    }
    return rmdir($dir);
  }
?>
3
ответ дан candlejack 31 August 2018 в 10:30
поделиться

Это работает для меня:

function removeDirectory($path) {
    $files = glob($path . '/*');
    foreach ($files as $file) {
        is_dir($file) ? removeDirectory($file) : unlink($file);
    }
    rmdir($path);
    return;
}
0
ответ дан Christopher Smit 31 August 2018 в 10:30
поделиться

2 цента, чтобы добавить к НАСТОЯЩИЙ ответ выше, что отличное BTW

После того, как ваша функция glob (или аналогичная) сканировала / прочитала каталог, добавьте условие для проверки ответ не пуст, или будет выдано предупреждение invalid argument supplied for foreach(). Итак ...

if( ! empty( $files ) )
{
    foreach( $files as $file )
    {
        // do your stuff here...
    }
}

Моя полная функция (как метод объекта):

    private function recursiveRemoveDirectory( $directory )
    {
        if( ! is_dir( $directory ) )
        {
            throw new InvalidArgumentException( "$directory must be a directory" );
        }

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

        $files = glob( $directory . "*" );

        if( ! empty( $files ) )
        {
            foreach( $files as $file )
            {
                if( is_dir( $file ) )
                {
                    $this->recursiveRemoveDirectory( $file );
                }
                else
                {
                    unlink( $file );
                }
            }               
        }
        rmdir( $directory );

    } // END recursiveRemoveDirectory()
7
ответ дан Community 31 August 2018 в 10:30
поделиться

Я не помню, откуда я скопировал эту функцию, но похоже, что она не указана, и она работает для меня

function rm_rf($path) {
    if (@is_dir($path) && is_writable($path)) {
        $dp = opendir($path);
        while ($ent = readdir($dp)) {
            if ($ent == '.' || $ent == '..') {
                continue;
            }
            $file = $path . DIRECTORY_SEPARATOR . $ent;
            if (@is_dir($file)) {
                rm_rf($file);
            } elseif (is_writable($file)) {
                unlink($file);
            } else {
                echo $file . "is not writable and cannot be removed. Please fix the permission or select a new path.\n";
            }
        }
        closedir($dp);
        return rmdir($path);
    } else {
        return @unlink($path);
    }
}
0
ответ дан dav 31 August 2018 в 10:30
поделиться
<?php
  function rrmdir($dir) {
  if (is_dir($dir)) {
    $objects = scandir($dir);
    foreach ($objects as $object) {
      if ($object != "." && $object != "..") {
        if (filetype($dir."/".$object) == "dir") 
           rrmdir($dir."/".$object); 
        else unlink   ($dir."/".$object);
      }
    }
    reset($objects);
    rmdir($dir);
  }
 }
?>

Попробуйте выставить код из php.net

Работайте со мной отлично

0
ответ дан Gaurang 31 August 2018 в 10:30
поделиться

Как видно из большинства проголосовавших комментариев на странице руководства PHP о rmdir() (см. http://php.net/manual/es/function.rmdir.php ), функция glob() не возвращать скрытые файлы. scandir() предоставляется в качестве альтернативы, которая решает эту проблему.

Алгоритм, описанный там (который работал как шарм в моем случае):

<?php 
    function delTree($dir)
    { 
        $files = array_diff(scandir($dir), array('.', '..')); 

        foreach ($files as $file) { 
            (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file"); 
        }

        return rmdir($dir); 
    } 
?>
11
ответ дан German Latorre 31 August 2018 в 10:30
поделиться

Вы можете использовать файловую систему Symfony ( code ):

// composer require symfony/filesystem

use Symfony\Component\Filesystem\Filesystem;

(new Filesystem)->remove($dir);

Однако я не смог удалить некоторые сложные структуры каталогов с помощью этого метода, поэтому сначала вы должны попробовать, чтобы убедиться, что он работает правильно.

Я мог бы удалить указанную структуру каталогов с помощью конкретной реализации Windows:

$dir = strtr($dir, '/', '\\');
// quotes are important, otherwise one could
// delete "foo" instead of "foo bar"
system('RMDIR /S /Q "'.$dir.'"');

И только ради полноты, вот мой старый код:

function xrmdir($dir) {
    $items = scandir($dir);
    foreach ($items as $item) {
        if ($item === '.' || $item === '..') {
            continue;
        }
        $path = $dir.'/'.$item;
        if (is_dir($path)) {
            xrmdir($path);
        } else {
            unlink($path);
        }
    }
    rmdir($dir);
}
7
ответ дан Gras Double 31 August 2018 в 10:30
поделиться

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

function deletePath($path) {
        if(is_file($path)){
            unlink($path);
        } elseif(is_dir($path)){
            $path = (substr($path, -1) !== DIRECTORY_SEPARATOR) ? $path . DIRECTORY_SEPARATOR : $path;
            $files = glob($path . '*');
            foreach ($files as $file) {
                deleteDirPath($file);
            }
            rmdir($path);
        } else {
            return false;
        }
}
0
ответ дан jay padaliya 31 August 2018 в 10:30
поделиться

Что-то вроде этого?

function delete_folder($folder) {
    $glob = glob($folder);
    foreach ($glob as $g) {
        if (!is_dir($g)) {
            unlink($g);
        } else {
            delete_folder("$g/*");
            rmdir($g);
        }
    }
}
1
ответ дан K-Gun 31 August 2018 в 10:30
поделиться

Изменение бита Litle кода alcuadrado - glob не видят файлы с именем из таких точек, как .htaccess, поэтому я использую scandir и сам скрипт удаляет себя - проверьте __FILE__.

function deleteDir($dirPath) {
    if (!is_dir($dirPath)) {
        throw new InvalidArgumentException("$dirPath must be a directory");
    }
    if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') {
        $dirPath .= '/';
    }
    $files = scandir($dirPath); 
    foreach ($files as $file) {
        if ($file === '.' || $file === '..') continue;
        if (is_dir($dirPath.$file)) {
            deleteDir($dirPath.$file);
        } else {
            if ($dirPath.$file !== __FILE__) {
                unlink($dirPath.$file);
            }
        }
    }
    rmdir($dirPath);
}
2
ответ дан karma_police 31 August 2018 в 10:30
поделиться

Я предпочитаю это, потому что он все еще возвращает TRUE, когда он преуспевает, и FALSE, когда он терпит неудачу, а также предотвращает ошибку, в которой пустые пути могут попробовать и удалить все из «/ *» !!:

function deleteDir($path)
{
    return !empty($path) && is_file($path) ?
        @unlink($path) :
        (array_reduce(glob($path.'/*'), function ($r, $i) { return $r && deleteDir($i); }, TRUE)) && @rmdir($path);
}
3
ответ дан Matt Connolly 31 August 2018 в 10:30
поделиться

Как решение Playnox, но с элегантным встроенным каталогом:

function delete_directory($dirPath){
 if(is_dir($dirPath)){
  $objects=new DirectoryIterator($dirPath);
   foreach ($objects as $object){
    if(!$object->isDot()){
     if($object->isDir()){
      delete_directory($object->getPathname());
     }else{
      unlink($object->getPathname());
     }
    }
   }
   rmdir($dirPath);
  }else{
   throw new Exception(__FUNCTION__.'(dirPath): dirPath is not a directory!');
  }
 }
0
ответ дан Matthew Slyman 31 August 2018 в 10:30
поделиться

Как насчет этого?

function Delete_Directory($Dir) 
{
  if(is_dir($Dir))
  {
      $files = glob( $Dir . '*', GLOB_MARK ); //GLOB_MARK adds a slash to directories returned

      foreach( $files as $file )
      {
          Delete_Directory( $file );      
      }
      if(file_exists($Dir))
      {
          rmdir($Dir);
      }
  } 
  elseif(is_file($Dir)) 
  {
     unlink( $Dir );  
  }
}

Refrence: https://paulund.co.uk/php-delete-directory-and-files-in-directory

0
ответ дан Mohamad Hamouday 31 August 2018 в 10:30
поделиться

Для окон:

system("rmdir ".escapeshellarg($path) . " /s /q");
0
ответ дан Mylo 31 August 2018 в 10:30
поделиться

Независимый от платформы код.

Взял ответ из PHP.net

if(PHP_OS === 'Windows')
{
 exec("rd /s /q {$path}");
}
else
{
 exec("rm -rf {$path}");
}
-4
ответ дан mysticmo 31 August 2018 в 10:30
поделиться

Простой и легкий ...

$dir ='pathtodir';
if (is_dir($dir)) {
  foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) {
    if ($filename->isDir()) continue;
    unlink($filename);
  }
  rmdir($dir);
}
0
ответ дан Newtron 31 August 2018 в 10:30
поделиться

Удалить все файлы в папке array_map('unlink', glob("$directory/*.*")); Удалить все. * - Файлы в папке (без: «.» и «..») array_map('unlink', array_diff(glob("$directory/.*),array("$directory/.","$directory/.."))) Теперь удалить саму папку rmdir($directory)

1
ответ дан PP2000 31 August 2018 в 10:30
поделиться

Пример для сервера Linux: exec('rm -f -r ' . $cache_folder . '/*');

0
ответ дан realmag777 31 August 2018 в 10:30
поделиться

Лучшее решение для меня

my_folder_delete("../path/folder");

код:

function my_folder_delete($path) {
    if(!empty($path) && is_dir($path) ){
        $dir  = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS); //upper dirs are not included,otherwise DISASTER HAPPENS :)
        $files = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::CHILD_FIRST);
        foreach ($files as $f) {if (is_file($f)) {unlink($f);} else {$empty_dirs[] = $f;} } if (!empty($empty_dirs)) {foreach ($empty_dirs as $eachDir) {rmdir($eachDir);}} rmdir($path);
    }
}

p.s. ЗАПОМНИТЬ! не пропускайте ПУСТОЙ ЦЕННОСТИ в любой каталог, удаляющий функции !!! (резервируйте их всегда, иначе в один прекрасный день вы можете получить БЕДСТВИЙ !!) [/ ​​g2]

2
ответ дан T.Todua 31 August 2018 в 10:30
поделиться

Вот идеальное решение:

function unlink_r($from) {
    if (!file_exists($from)) {return false;}
    $dir = opendir($from);
    while (false !== ($file = readdir($dir))) {
        if ($file == '.' OR $file == '..') {continue;}

        if (is_dir($from . DIRECTORY_SEPARATOR . $file)) {
            unlink_r($from . DIRECTORY_SEPARATOR . $file);
        }
        else {
            unlink($from . DIRECTORY_SEPARATOR . $file);
        }
    }
    rmdir($from);
    closedir($dir);
    return true;
}
1
ответ дан Tarik 31 August 2018 в 10:30
поделиться

Обычно я использую это для удаления всех файлов в папке:

array_map('unlink', glob("$dirname/*.*"));

И вы можете сделать

rmdir($dirname);
152
ответ дан user3033886 31 August 2018 в 10:30
поделиться

Это более короткая версия отлично работает для меня

function deleteDirectory($dirPath) {
    if (is_dir($dirPath)) {
        $objects = scandir($dirPath);
        foreach ($objects as $object) {
            if ($object != "." && $object !="..") {
                if (filetype($dirPath . DIRECTORY_SEPARATOR . $object) == "dir") {
                    deleteDirectory($dirPath . DIRECTORY_SEPARATOR . $object);
                } else {
                    unlink($dirPath . DIRECTORY_SEPARATOR . $object);
                }
            }
        }
    reset($objects);
    rmdir($dirPath);
    }
}
18
ответ дан user6972 31 August 2018 в 10:30
поделиться

Я хочу расширить ответ @alcuadrado с комментариями @Vijit для обработки символических ссылок. Во-первых, используйте getRealPath (). Но тогда, если у вас есть какие-либо символические ссылки, которые являются папками, это провалится, поскольку он попытается вызвать rmdir по ссылке - так что вам нужна дополнительная проверка.

$it = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
foreach($files as $file) {
    if ($file->isLink()) {
        unlink($file->getPathname());
    } else if ($file->isDir()){
        rmdir($file->getPathname());
    } else {
        unlink($file->getPathname());
    }
}
rmdir($dir);
2
ответ дан user701152 31 August 2018 в 10:30
поделиться

Какой самый простой способ удалить каталог со всеми его файлами в нем?

system("rm -rf ".escapeshellarg($dir));
72
ответ дан Your Common Sense 31 August 2018 в 10:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: