ファイルが入っているディレクトリを削除しますか?


245

すべてのファイルが含まれているディレクトリを削除する最も簡単な方法は何でしょうか。

rmdir(PATH . '/' . $value);フォルダーの削除に使用していますが、フォルダー内にファイルがあると削除できません。



2
うん、その質問で正確に答えました。
timdev

注意したいだけです。複数のファイルを作成しましたが、処理中にエラーが発生した場合は、以前に作成したファイルを削除する必要があります。ファイルを作成したときに使用するのfclose($create_file);を忘れ、削除したときにを得たWarning: unlink(created_file.xml): Permission denied in...。したがって、このようなエラーを回避するには、作成されたファイルを閉じる必要があります。
アンドリス、2015

回答:


381

現在、少なくとも2つのオプションが利用可能です。

  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
2番目の実装はやや危険です。ドット(.および..)をチェックせず、実際のパスではなく解決されたパスを削除します。
Alix Axel

9
小さなアドオン:-) glob()は.htaccessのようなファイルをサポートしていません。.htaccessと.thumbs(ファイル+フォルダー)の両方を生成するKCFinder(CKEditorプラグイン)によって作成されたディレクトリをクリアする関数を使用しました。代わりに、scandir関数を使用してフォルダーリストを取得しました。「。」をフィルタリングすることを確認してください。結果リストの「..」ファイル。
ジョシュア-ペンド

25
OS に送信するパスを構築する場合、DIRECTORY_SEPARATORは必要ありません。Windowsはスラッシュも受け入れます。これは主に、OS からexplode()取得たパスを使用するのに役立ちます。alanhogan.com/tips/php/directory-separator-not-necessary
ReactiveRaven

5
@Alix Axelに加えて、ここで[SplFileInfo :: getRealPath()](php.net/manual/en/splfileinfo.getrealpath.php)を使用することはお勧めできません。このメソッドはすべてのシンボリックリンクを展開します。つまり、ターゲットディレクトリからのシンボリックリンクではなく、どこかから実際のファイルが削除されます。代わりにSplFileInfo :: getPathname()を使用する必要があります。
Vijit 2016年

2
@Vijitに同意します。getRealPath()ではなくgetPathname()を使用します。シンボリックリンクが見つかった場合に期待する以上のものを削除せずに同じことを行います。
JoeMoe1984

196

私は通常、これを使用してフォルダー内のすべてのファイルを削除します。

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

そして、あなたはできる

rmdir($dirname);

26
これはフォルダを再帰的に削除するものではありません。フォルダーに通常のファイルのみがあり、そのすべてにファイル拡張子が付いている場合にのみ機能します。
mgnb 2015

5
再帰が必要ない場合、これがこれまでのところ最良かつ最も簡単な答えです。ありがとう!
eisbehr 2016年

2
拡張子のあるファイルだけでなく、フォルダーからすべてのファイルを削除するには、次のようにglobを使用します。array_map('unlink', glob("$dirname/*"));これでも、フォルダーにネストされているディレクトリを削除することはできません。
kremuwa

これにより、ドット(非表示)ファイルも削除されることに注意してください。
BadHorsie

85

ファイルがすべて含まれているディレクトリを削除する最も簡単な方法は何ですか?

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

33
真剣ではないことを望みます。$ dirが/の場合はどうなりますか
Pixel開発者

108
@上記のコードとまったく同じです。だよね?
常識

7
方法に応じて、 $dir生成/提供のは、安全を確保し、バグを回避するために、追加の前処理が必要になる場合があります。たとえば$dir、エスケープされていないスペースやセミコロンが含まれている可能性がある場合、望ましくない副作用が発生する可能性があります。これはrmdir()、特殊文字を処理するため、次のようなものを使用する回答には当てはまりません。
Trott

5
Windowsバージョン: system('rmdir '.escapeshellarg($path).' /s /q');
Cypher

2
@ThePixelDeveloper /の削除について心配する必要はありません。これは、コマンドラインでスクリプトをrootとして起動した場合にのみ機能します。これは、WebではすべてがApacheユーザーとして行われるためです
ベン

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__);
Matt Connolly

2
誰かがラインを説明できますかarray_map($class_func, glob($path.'/*')) == @rmdir($path)?彼はサブフォルダーを再帰していると思いますが、== @rmdir部分は何をしているのですか?<ブールの配列> == <ブール>はどのように答えを返しますか?再帰の各戻り値が右側のブール値と同じかどうかをチェックしますか?
arviman 2013年

2
2つのステートメントを1つのステートメントにマージするのはトリックです。これは、3項演算子では、引数ごとに1つのステートメントしか使用できないためです。array_map(...)ディレクトリ内のすべてのファイルを@rmdir(...)削除し、ディレクトリ自体を削除します。
ブレーズ

3
注意してください!この関数は、パスが実際に存在するかどうかはチェックしません。空の引数を渡すと、関数はルートからファイルの削除を開始します!この関数を実行する前に、パスに健全性チェックを追加してください。
Tatu Ulmanen 2014年

3
一部の人々はタツのコメントを見ずに再帰的に削除/したので、私は私の保護されたバージョンを私の投稿に追加しました。
ブレーズ、2014年

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です。
ドイツのラトーレ

私は正直に言って、このような変数を連結できることを知りませんでした:) 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のファイルシステムコード)を使用できます:

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

「車輪を再発明しないでください」。ありがとう
Kamafeather

9

ここに、そのディレクトリを含むソースディレクトリ内のすべてのファイルを削除するための1つの素晴らしく単純な再帰があります。

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

PS覚えて!
空の値をディレクトリ削除関数に渡さないでください!!! (常にバックアップしてください。そうしないと、いつかDISASTERになるかもしれません!!)


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

シンボリックリンクを処理するための@Vijitのコメントとともに、@ alcuadradoの回答を拡張したいと思います。まず、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);

1
回答に直接コメントするのに十分な担当者がいません。
user701152 2017

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ポイントから名前の付いたファイルが表示されない.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

Linuxサーバーの例: exec('rm -f -r ' . $cache_folder . '/*');


私は通常、コストのかかる間違いを避けるために、rm -rfを実行する前に$ cache_folderの健全性チェックを追加したい
グリフ

1

フォルダ内のすべてのファイルを削除します
array_map('unlink', glob("$directory/*.*"));
。フォルダ内のすべての。*-ファイルを削除します(「。」および「..」なし)
array_map('unlink', array_diff(glob("$directory/.*),array("$directory/.","$directory/..")))
。次に、フォルダ自体を削除します。
rmdir($directory)


1

上記のこの答えに追加する2セントは、すばらしいBTWです

グロブ(または類似の)関数がディレクトリをスキャンまたは読み取った後、条件を追加して応答が空でないことを確認し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(array)-ディレクトリの削除用。有効なオプションは次のとおりです。traverseSymlinks:ブール値。ディレクトリへのシンボリックリンクもトラバースする必要があるかどうか。デフォルトfalseはです。これは、symlinkedディレクトリのコンテンツが削除されないことを意味します。そのデフォルトの場合、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 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 );  
  }
}

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


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.