Cancellare tutti i file da una cartella usando PHP?


306

Ad esempio avevo una cartella chiamata "Temp" e volevo cancellare o svuotare tutti i file da questa cartella usando PHP. Potrei farlo?


14
È positivo che a questa domanda sia stata data una risposta prima di essere contrassegnata come duplicata. Le risposte di seguito sono molto meglio della domanda con risposta collegata. Inoltre la domanda è diversa, questa domanda chiede di svuotare una directory, non di eliminarla.
Bart Burg,

1
Sì, questa è una domanda diversa che ha dato risposte diverse. Non dovrebbe essere contrassegnato come duplicato.
Daniel Bingham,

Risposte:


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

Se vuoi rimuovere file "nascosti" come .htaccess, devi usare

$files = glob('path/to/temp/{,.}*', GLOB_BRACE);

4
Inoltre c'è DirectoryIterator o DirectoryRecursiveIterator.
Eugene,

6
Anche se è ovvio, vorrei dire che, ad esempio, "percorso / a / temp / *. Txt" rimuoverà solo i file txt e così via.
Tertium,

Funziona anche con percorsi relativi? Supponiamo quindi che il percorso completo sia "/ var / www / html / folder_and_files_to_delete /" E lo script di eliminazione è inserito in "/var/www/html/delete_folders_and_files.php". Posso semplicemente prendere "folder_and_files_to_delete" come percorso?
Yoano

1
@yoano si certo, purché il percorso relativo sia corretto.
Floern

Glob è OK se la directory contiene decine di migliaia o centinaia di migliaia di file?
Dave Heq,

260

Se si desidera eliminare tutto, dalla cartella (compresi sottocartelle) usare questa combinazione di array_map, unlinke glob:

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

Questa chiamata può anche gestire directory vuote (grazie per il suggerimento, @mojuba!)


33
La migliore risposta, grazie. Per evitare le comunicazioni farei anche glob("...") ?: [](PHP 5.4+) perché glob()ritorna una directory vuota false.
Mojuba,

14
Elimina tutti i file nella cartella corrente, ma restituisce un avviso per le sottocartelle e non li elimina.
Key-Six

2
Combinando le risposte di Stichoza e mojuba:array_map('unlink', ( glob( "path/to/temp/*" ) ? glob( "path/to/temp/*" ) : array() ) );
Ewout

7
@Ewout: anche se uniamo la risposta di Stichoza e Moujuba poiché la tua donazione restituisce lo stesso avvertimento per le sottocartelle e non le elimina
Sulthan Allaudeen,

3
Purtroppo questo non elimina le sottocartelle.
tmarois,

92

Ecco un approccio più moderno che utilizza la libreria 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;

1
Funziona bene, quando non hai accesso SSH e FTP impiega letteralmente ore per ricorsivo eliminare molti file e cartelle ... con quelle righe ho eliminato 35000 file in meno di 3 secondi!
guari,

Per gli utenti di PHP 7.1: utilizzare $ file-> getRealPath () anziché $ file. Altrimenti, PHP ti darà un errore dicendo che unlink richiede un percorso, non un'istanza di SplFileInfo.
KeineMaster,

68
foreach (new DirectoryIterator('/path/to/directory') as $fileInfo) {
    if(!$fileInfo->isDot()) {
        unlink($fileInfo->getPathname());
    }
}

dovrebbe essere unlink ('/ path / to / directory /'.$ fileInfo-> getFilename ()); poiché unlink prende il percorso. Buona risposta però.
Vic

8
Si potrebbe anche fare unlink ($ fileInfo-> getPathname ()); che ti darebbe il percorso completo del file. php.net/manual/en/directoryiterator.getpathname.php
Josh Holloway

'DirectoryIterator' non scorre anche nelle sottodirectory? In tal caso, "unlink" genererebbe un avviso in tali casi. Il corpo del loop non dovrebbe apparire più simile nella risposta di Yamiko e controllare ogni voce se è un file prima di chiamare 'unlink'?
Andreas Linnert,

19

Questo codice da 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

Vedi readdir e scollega .

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

10

Supponendo che tu abbia una cartella con MOLTI file per leggerli tutti e poi eliminarli in due passaggi non è così performante. Credo che il modo più efficace per eliminare i file sia semplicemente usare un comando di sistema.

Ad esempio su Linux utilizzo:

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

O questo se si desidera la cancellazione ricorsiva senza la necessità di scrivere una funzione ricorsiva

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

esistono gli stessi comandi esatti per qualsiasi sistema operativo supportato da PHP. Tieni presente che questo è un modo PERFORMANTE di eliminare i file. $ absolutePathToFolder DEVE essere verificato e protetto prima di eseguire questo codice e le autorizzazioni devono essere concesse.


2
Un po 'pericoloso usando questo metodo, se $absolutePatToFoldermai è vuoto
Lawrence Cherone

@LawrenceCherone Le altre alternative sono più sicure?
robsch,

3
@LawrenceCherone Spero che nessuno esegua php con i permessi di root al giorno d'oggi. Essendo serio, mi aspetto che l'input sia "sicuro", poiché tutte le funzioni di cui sopra.
Dario Corno,

Le soluzioni più votate non funzionano in ambienti di sviluppo in cui www o www-data non è il proprietario. Spetta all'amministratore del server assicurarsi che siano impostati i diritti corretti della cartella. exec è uno strumento inestimabile per fare le cose, e con grande potenza, ecc. stackoverflow.com/a/2765171/418974
Christian Bonato

@LawrenceCherone hai perfettamente ragione, la mia risposta è stata pensata per una situazione molto specifica, solo per motivi di prestazioni. Modificata la mia risposta in base alle tue note.
Dario Corno,


4

Un'altra soluzione: questa classe elimina tutti i file, le sottodirectory e i file nelle sottodirectory.

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

La funzione unlinkr elimina in modo ricorsivo tutte le cartelle e i file in un determinato percorso assicurandosi che non elimini lo script stesso.

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

se si desidera eliminare tutti i file e le cartelle in cui si inserisce questo script, chiamarlo come segue

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

se vuoi eliminare solo i file php, chiamalo come segue

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

puoi usare qualsiasi altro percorso per eliminare anche i file

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

Ciò eliminerà tutti i file nella directory home / user / temp.


3

Inserito un file di uso generale e una classe di gestione delle cartelle per la copia, lo spostamento, l'eliminazione, il calcolo delle dimensioni e così via, in grado di gestire un singolo file o un set di cartelle.

https://gist.github.com/4689551

Usare:

Per copiare (o spostare) un singolo file o un set di cartelle / file:

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

Elimina un singolo file o tutti i file e le cartelle in un percorso:

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

Calcola la dimensione di un singolo file o di un set di file in un set di cartelle:

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

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

1

Per me, la soluzione è readdirstata la migliore e ha funzionato come un fascino. Con glob, la funzione stava fallendo con alcuni scenari.

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

Ho aggiornato la risposta di @Stichoza per rimuovere i file tramite le sottocartelle.

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

C'è un pacchetto chiamato "Pusheh". Usandolo, puoi cancellare una directory o rimuovere completamente una directory ( link Github ). È disponibile anche su Packagist .

Ad esempio, se si desidera cancellare la Tempdirectory, è possibile eseguire:

Pusheh::clearDir("Temp");

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

Se sei interessato, consulta il wiki .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.