Supprimer tous les fichiers d'un dossier en utilisant PHP?

306

Par exemple, j'avais un dossier appelé «Temp» et je voulais supprimer ou vider tous les fichiers de ce dossier en utilisant PHP. Puis-je faire ça?

va-t-en
la source
14
C'est une bonne chose que cette question ait été répondue ci-dessous avant d'être marquée comme doublon. Les réponses ci-dessous sont bien meilleures que la question à réponse liée. De plus, la question est différente, cette question demande de vider un répertoire, pas de le supprimer.
Bart Burg
1
Oui, c'est une question différente qui a attiré des réponses différentes. Il ne doit pas être marqué comme doublon.
Daniel Bingham

Réponses:

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

Si vous souhaitez supprimer des fichiers «cachés» comme .htaccess, vous devez utiliser

$files = glob('path/to/temp/{,.}*', GLOB_BRACE);
Floern
la source
4
Il existe également DirectoryIterator ou DirectoryRecursiveIterator.
Eugene
6
Bien que cela soit évident, je mentionnerais que, par exemple, 'path / to / temp / *. Txt' supprimera uniquement les fichiers txt et ainsi de suite.
Tertium
Cela fonctionne-t-il également pour les chemins relatifs? Supposons donc que le chemin complet soit "/ var / www / html / folder_and_files_to_delete /" Et que le script de suppression soit placé dans "/var/www/html/delete_folders_and_files.php". Puis-je simplement prendre "folder_and_files_to_delete" comme chemin?
yoano
1
@yoano oui bien sûr, tant que le chemin relatif est correct.
Floern
Glob est-il correct à utiliser si le répertoire contient des dizaines de milliers ou des centaines de milliers de fichiers?
Dave Heq
260

Si vous voulez supprimer tout du dossier (y compris les sous - dossiers) utiliser cette combinaison de array_map, unlinket glob:

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

Cet appel peut également gérer des répertoires vides (merci pour l'astuce, @mojuba!)

Stichoza
la source
33
Meilleure réponse, merci. Pour éviter les notifications, je le ferais aussi glob("...") ?: [](PHP 5.4+) car pour un répertoire vide glob()retourne false.
mojuba
14
Il supprime tous les fichiers du dossier actuel, mais il renvoie un avertissement pour les sous-dossiers et ne les supprime pas.
Key-Six
2
Combiner les réponses de Stichoza et de mojuba:array_map('unlink', ( glob( "path/to/temp/*" ) ? glob( "path/to/temp/*" ) : array() ) );
Ewout
7
@Ewout: Même si nous combinons la réponse de Stichoza et de Moujuba alors que votre don renvoie le même avertissement pour les sous-dossiers et ne les supprime pas
Sulthan Allaudeen
3
Malheureusement, cela ne supprime pas les sous-dossiers.
tmarois
92

Voici une approche plus moderne utilisant la bibliothèque PHP standard (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
la source
1
Cela fonctionne bien, lorsque vous n'avez pas d'accès SSH et que FTP prend littéralement des heures pour supprimer récursivement de nombreux fichiers et dossiers ... avec ces lignes, j'ai supprimé 35000 fichiers en moins de 3 secondes!
guari
Pour les utilisateurs de PHP 7.1: $ file-> getRealPath () doit être utilisé à la place de $ file. Sinon, PHP vous donnera une erreur indiquant que la dissociation nécessite un chemin, pas une instance de SplFileInfo.
KeineMaster
68
foreach (new DirectoryIterator('/path/to/directory') as $fileInfo) {
    if(!$fileInfo->isDot()) {
        unlink($fileInfo->getPathname());
    }
}
JakeParis
la source
il doit être dissocié ('/ chemin / vers / répertoire /'.$ fileInfo-> getFilename ()); puisque la dissociation prend le chemin. Bonne réponse cependant.
Vic
8
Vous pouvez même faire un lien ($ fileInfo-> getPathname ()); qui vous donnerait le chemin d'accès complet au fichier. php.net/manual/en/directoryiterator.getpathname.php
Josh Holloway
'DirectoryIterator' n'itère-t-il pas également les sous-répertoires? Si tel est le cas, «dissocier» générerait un avertissement dans de tels cas. Le corps de la boucle ne devrait-il pas plutôt ressembler davantage à la réponse de Yamiko et vérifier chaque entrée s'il s'agit d'un fichier avant d'appeler 'unlink'?
Andreas Linnert
19

Ce code de 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);
    }
}
Poelinca Dorin
la source
16
$dir = 'your/directory/';
foreach(glob($dir.'*.*') as $v){
    unlink($v);
}
Haim Evgi
la source
11

Voir readdir et unlink .

<?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
la source
10

En supposant que vous ayez un dossier avec BEAUCOUP de fichiers en les lisant tous, puis en les supprimant en deux étapes, ce n'est pas si performant. Je pense que la façon la plus efficace de supprimer des fichiers est d'utiliser simplement une commande système.

Par exemple sur Linux j'utilise:

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

Ou ceci si vous voulez une suppression récursive sans avoir besoin d'écrire une fonction récursive

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

les mêmes commandes existent pour tout OS supporté par PHP. Gardez à l'esprit qu'il s'agit d'une manière PERFORMANTE de supprimer des fichiers. $ absoluePathToFolder DOIT être vérifié et sécurisé avant d'exécuter ce code et des autorisations doivent être accordées.

Dario Corno
la source
2
Bit dangereux à l'aide de cette méthode, si $absolutePatToFolderjamais vide
Lawrence Cherone
@LawrenceCherone D'autres alternatives sont-elles plus sûres?
robsch
3
@ LawrenceCherone J'espère que personne n'exécute php avec les autorisations root de nos jours. Étant sérieux, je m'attends à ce que l'entrée soit "sécurisée", comme toutes les fonctions ci-dessus.
Dario Corno du
Les solutions les plus votées ne fonctionnent pas dans les environnements de développement où www ou www-data n'est pas le propriétaire. Il appartient à l'administrateur du serveur de s'assurer que les droits appropriés du dossier sont définis. exec est un outil inestimable pour faire avancer les choses, avec une grande puissance, etc. stackoverflow.com/a/2765171/418974
Christian Bonato
@ LawrenceCherone vous avez totalement raison ma réponse était destinée à une situation très spécifique, juste pour des raisons de performances. Modifié ma réponse en fonction de vos notes.
Dario Corno
4

Une autre solution: cette classe supprime tous les fichiers, sous-répertoires et fichiers des sous-répertoires.

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."/*"));
        }
    }
}
tommy
la source
4

La fonction unlinkr supprime récursivement tous les dossiers et fichiers d'un chemin donné en s'assurant qu'elle ne supprime pas le script lui-même.

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

si vous souhaitez supprimer tous les fichiers et dossiers dans lesquels vous placez ce script, appelez-le comme suit

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

si vous voulez simplement supprimer uniquement les fichiers php, appelez-le comme suit

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

vous pouvez également utiliser tout autre chemin pour supprimer les fichiers

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

Cela supprimera tous les fichiers du répertoire home / user / temp.

Tofeeq
la source
3

Publié une classe de gestion de fichiers et de dossiers à usage général pour copier, déplacer, supprimer, calculer la taille, etc., qui peut gérer un seul fichier ou un ensemble de dossiers.

https://gist.github.com/4689551

Utiliser:

Pour copier (ou déplacer) un seul fichier ou un ensemble de dossiers / fichiers:

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

Supprimez un seul fichier ou tous les fichiers et dossiers d'un chemin:

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

Calculez la taille d'un seul fichier ou d'un ensemble de fichiers dans un ensemble de dossiers:

$files = new Files();
$results = $files->calculateSize('source/folder/optional-file.name');
AmyStephen
la source
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
la source
1

Pour moi, la solution readdirétait la meilleure et fonctionnait comme un charme. Avec glob, la fonction échouait avec certains scénarios.

// 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);
}
Tiago Silva Pereira
la source
0

J'ai mis à jour la réponse de @Stichoza pour supprimer les fichiers via les sous-dossiers.

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));
}
tzi
la source
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);
}
Mehmet
la source
0

Il y a un paquet appelé "Pusheh". En l'utilisant, vous pouvez effacer un répertoire ou supprimer complètement un répertoire ( lien Github ). Il est également disponible sur Packagist .

Par exemple, si vous souhaitez effacer le Temprépertoire, vous pouvez faire:

Pusheh::clearDir("Temp");

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

Si vous êtes intéressé, consultez le wiki .

MAChitgarha
la source