파일이있는 디렉토리를 삭제 하시겠습니까?


246

모든 파일이 들어있는 디렉토리를 삭제하는 가장 쉬운 방법은 무엇입니까?

rmdir(PATH . '/' . $value);폴더를 삭제하는 데 사용 하고 있지만 폴더 안에 파일이 있으면 삭제할 수 없습니다.



2
응, 그 질문에 정확히 대답했다.
timdev

참고하고 싶을뿐입니다. 여러 파일을 만들었으며 프로세스 중에 오류가 발생하면 이전에 만든 파일을 삭제해야합니다. 파일을 만들 때 사용을 잊어 버렸고 fclose($create_file);삭제 할 때 얻었습니다 Warning: unlink(created_file.xml): Permission denied in.... 따라서 이러한 오류를 피하려면 작성된 파일을 닫아야합니다.
Andris

답변:


382

요즘에는 두 가지 이상의 옵션이 있습니다.

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

11
두 번째 구현은 다소 위험합니다. 점 ( ...)을 확인하지 않고 실제 경로가 아닌 해결 된 경로를 삭제합니다.
Alix Axel

9
작은 애드온 :-) glob ()는 .htaccess와 같은 파일을 지원하지 않습니다. 이 기능을 사용하여 .htaccess와 .thumbs (파일 + 폴더)를 생성하는 KCFinder (CKEditor 플러그인)로 만든 디렉토리를 지우 었습니다. 대신 scandir폴더 목록을 가져 오기 위해 함수를 사용했습니다 . '.'을 필터링하십시오. 및 결과 목록에서 '..'파일.
Joshua-Pendo 2016 년

25
보낼 경로를 구축 할 때 DIRECTORY_SEPARATOR는 필요하지 않습니다 운영 체제. Windows는 슬래시도 허용합니다. 주로 OS 에서explode() 가져온 경로 를 ing하는 데 유용합니다 . alanhogan.com/tips/php/directory-separator-not-recessary
ReactiveRaven

5
@Alix Axel 외에도 여기에 [SplFileInfo :: getRealPath ()] ( php.net/manual/en/splfileinfo.getrealpath.php )를 사용하는 것은 좋지 않습니다. 이 방법은 모든 심볼릭 링크를 확장합니다. 즉, 대상 디렉토리의 심볼릭 링크 대신 어딘가에서 실제 파일이 삭제됩니다. 대신 SplFileInfo :: getPathname ()을 사용해야합니다.
Vijit

2
@Vijit에 동의합니다. getRealPath () 대신 getPathname ()을 사용하십시오. 심볼릭 링크가 발견되면 예상보다 많은 것을 삭제하지 않고 동일한 작업을 수행합니다.
JoeMoe1984

196

나는 일반적으로 이것을 사용하여 폴더의 모든 파일을 삭제합니다.

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

그리고 당신은 할 수 있습니다

rmdir($dirname);

27
폴더를 재귀 적으로 삭제하지는 않습니다. 폴더에 파일 확장자가있는 일반 파일 만있는 경우에만 작동합니다.
mgnb

5
재귀가 필요하지 않으면 지금까지 가장 훌륭하고 간단한 대답입니다. 감사!
eisbehr

2
확장자가있는 파일뿐만 아니라 폴더에서 모든 파일 을 제거 하려면 다음 방법으로 glob를 사용하십시오. array_map('unlink', glob("$dirname/*"));그래도 폴더에 중첩 된 디렉토리는 삭제할 수 없습니다.
kremuwa

이렇게하면 점 (숨겨진) 파일도 제거됩니다.
BadHorsie

84

파일이 들어있는 디렉토리를 삭제하는 가장 쉬운 방법은 무엇입니까?

system("rm -rf ".escapeshellarg($dir));

33
난 당신이 심각하지 않기를 바랍니다. $ dir이 / 인 경우 어떻게됩니까
픽셀 개발자

108
@ 위의 코드와 동일합니다. 그렇지 않습니까?
당신의 상식

7
$dir생성 / 제공 방법에 따라 안전하고 버그를 피하기 위해 추가 사전 처리를 수행해야 할 수도 있습니다. 예를 들어, $dir이스케이프되지 않은 공간이나 세미콜론이 있으면 바람직하지 않은 부작용이있을 수 있습니다. rmdir()특수 문자를 처리하기 때문에 이와 같은 답변을 사용하는 경우에는 그렇지 않습니다 .
Trott

5
Windows 버전 :system('rmdir '.escapeshellarg($path).' /s /q');
Cypher

2
@ThePixelDeveloper / 삭제에 대해 걱정할 필요가 없습니다. / 웹에서 모든 것이 아파치 사용자로 발생하기 때문에 명령 줄에서 스크립트를 루트로 시작한 경우에만 작동합니다.
Ben

49

일을하는 짧은 기능 :

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

큰 힘을 가지고 큰 책임을집니다 . 빈 값으로이 함수를 호출하면 루트 ( /)로 시작하는 파일이 삭제됩니다 . 안전을 위해 경로가 비어 있는지 확인할 수 있습니다.

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

1
정적 함수는 클래스에서 정적 함수를 호출 할 때 $ this === NULL이므로 작동하지 않습니다. 이 경우 일 것이다$this_func = array(__CLASS__, __FUNCTION__);
매트 코놀리

2
누군가 줄을 설명 할 수 있습니까 array_map($class_func, glob($path.'/*')) == @rmdir($path)? 나는 그가 하위 폴더를 통해 재귀하고 있다고 생각하지만 == @rmdir 부분은 무엇을합니까? <부울 배열> == <부울>은 어떻게 대답을 반환합니까? 재귀의 각 반환 값이 오른쪽의 부울과 같은지 확인합니까?
arviman

2
두 문장을 하나의 문장으로 병합하는 것은 속임수입니다. 삼항 연산자는 인수 당 하나의 명령문 만 허용하기 때문입니다. array_map(...)디렉토리 내의 모든 파일을 @rmdir(...)제거하고 디렉토리 자체를 제거합니다.
Blaise

3
조심해! 이 기능은 경로가 실제로 존재하는지 확인하지 않습니다. 빈 인수를 전달하면 함수는 루트에서 시작하여 파일을 삭제하기 시작합니다! 이 기능을 실행하기 전에 경로에 위생 검사를 추가하십시오.
Tatu Ulmanen

3
어떤 사람들은 Tatu의 의견을 보지 않고 재귀 적으로 삭제 /했기 때문에 게시물에 보호 버전을 추가했습니다.
Blaise

22

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

is_dir ( "$ dir / $ file")을 설명해 주시겠습니까? "$ dir / $ file"매개 변수를 충족하지 못했습니다
Igor L.

무슨 소리 야? 디렉토리 ( $file) 에있는 항목 이 디렉토리인지 파일인지 확인합니다. "$dir/$file"와 동일합니다 $dir . "/" . $file.
독일 Latorre

나는 솔직히 당신이 다음과 같은 변수를 연결할 수 있다는 것을 몰랐습니다 :) thx
Igor L.

18

이것은 짧은 버전입니다 나에게 잘 작동합니다

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

15

Symfony 's Filesystem ( 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);
}

고마워요. 시간을 절약하세요.
zarif khan

"바퀴를 재발 명하지 마십시오" . 감사합니다
Kamafeather

9

다음은 해당 디렉토리를 포함하여 소스 디렉토리의 모든 파일을 삭제하기위한 훌륭하고 간단한 재귀입니다.

function delete_dir($src) { 
    $dir = opendir($src);
    while(false !== ( $file = readdir($dir)) ) { 
        if (( $file != '.' ) && ( $file != '..' )) { 
            if ( is_dir($src . '/' . $file) ) { 
                delete_dir($src . '/' . $file); 
            } 
            else { 
                unlink($src . '/' . $file); 
            } 
        } 
    } 
    closedir($dir); 
    rmdir($src);

}

기능은 디렉토리 복사를 위해 만들어진 재귀를 기반으로합니다. 해당 기능을 여기에서 찾을 수 있습니다 : PHP를 사용하여 디렉토리의 전체 내용을 다른 디렉토리로 복사 하십시오.


4

나를위한 최고의 솔루션

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

추억!
비어있는 값을 모든 디렉토리 삭제 기능에 전달하지 마십시오 !!! (항상 백업하십시오. 그렇지 않으면 언젠가는 재난을 겪을 수 있습니다!)


4

이건 어때?

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

4

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

4

다음과 같이 시도 할 수 있습니다.

/*
 * Remove the directory and its content (all files and subdirectories).
 * @param string $dir the directory name
 */
function rmrf($dir) {
    foreach (glob($dir) as $file) {
        if (is_dir($file)) { 
            rmrf("$file/*");
            rmdir($file);
        } else {
            unlink($file);
        }
    }
}

3

나는 이것이 성공하면 여전히 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

@aljiadrado의 답변을 @Vijit의 심볼릭 링크 처리와 함께 확장하고 싶습니다. 먼저 getRealPath ()를 사용하십시오. 그러나 폴더 인 symlinks가 있으면 링크에서 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);

1
답변에 직접 언급 할 담당자가 충분하지 않습니다.
user701152

3

이전 답변과 동등한 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);
}

3

이것은 나를 위해 작동합니다 :

function removeDirectory($path) {
    $files = glob($path . '/*');
    foreach ($files as $file) {
        is_dir($file) ? removeDirectory($file) : unlink($file);
    }
    rmdir($path);
    return;
}

2

이 같은?

function delete_folder($folder) {
    $glob = glob($folder);
    foreach ($glob as $g) {
        if (!is_dir($g)) {
            unlink($g);
        } else {
            delete_folder("$g/*");
            rmdir($g);
        }
    }
}

2

alcuadrado 코드의 작은 비트 수정- glob같은 이름의 파일이 표시되지 않으므로 .htaccessscandir을 사용하고 스크립트는 자체 검사를 삭제합니다 __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

Linux 서버의 예 : exec('rm -f -r ' . $cache_folder . '/*');


일반적으로 같은 나는 비용이 많이 드는 실수를 방지하기 위해 RF RM은 프로그램을 실행하기 전에 $ cache_folder의 전성 검사를 추가
문양을

1

폴더의 모든 파일 삭제 폴더의
array_map('unlink', glob("$directory/*.*"));
모든. *-파일 삭제 ( "."및 ".."제외)
array_map('unlink', array_diff(glob("$directory/.*),array("$directory/.","$directory/..")))
폴더 자체를 삭제하십시오.
rmdir($directory)


1

위의 답변 에 추가 할 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()

1

완벽하게 작동하는 솔루션은 다음과 같습니다.

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

YII 도우미를 복사 할 수 있습니다

$ directory (string)-재귀 적으로 삭제됩니다.

$ options (배열)-디렉토리 제거 용. 유효한 옵션은 다음과 같습니다. traverseSymlinks : 부울, 디렉토리에 대한 symlink도 순회해야하는지 여부. 기본값은 false이며 심볼릭 링크 된 디렉토리의 내용은 삭제되지 않습니다. 해당 기본 경우에는 symlink 만 제거됩니다.

public static function removeDirectory($directory,$options=array())
{
    if(!isset($options['traverseSymlinks']))
        $options['traverseSymlinks']=false;
    $items=glob($directory.DIRECTORY_SEPARATOR.'{,.}*',GLOB_MARK | GLOB_BRACE);
    foreach($items as $item)
    {
        if(basename($item)=='.' || basename($item)=='..')
            continue;
        if(substr($item,-1)==DIRECTORY_SEPARATOR)
        {
            if(!$options['traverseSymlinks'] && is_link(rtrim($item,DIRECTORY_SEPARATOR)))
                unlink(rtrim($item,DIRECTORY_SEPARATOR));
            else
                self::removeDirectory($item,$options);
        }
        else
            unlink($item);
    }
    if(is_dir($directory=rtrim($directory,'\\/')))
    {
        if(is_link($directory))
            unlink($directory);
        else
            rmdir($directory);
    }
}

0
<?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

Playnox의 솔루션과 마찬가지로 우아한 내장 DirectoryIterator를 사용하십시오.

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

이 함수를 어디에서 복사했는지 기억이 나지 않지만 목록에없는 것처럼 보이고 작동합니다.

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

간단하고 쉬운 ...

$dir ='pathtodir';
if (is_dir($dir)) {
  foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) {
    if ($filename->isDir()) continue;
    unlink($filename);
  }
  rmdir($dir);
}


0

확실하지 않은 경우 주어진 경로는 디렉토리 또는 파일입니다.이 기능을 사용하여 경로를 삭제할 수 있습니다

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;
        }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.