Usunąć wszystkie pliki z folderu za pomocą PHP?


306

Na przykład miałem folder o nazwie „Temp” i chciałem usunąć lub opróżnić wszystkie pliki z tego folderu za pomocą PHP. Czy mogę to zrobić?


14
Dobrze, że na pytanie to udzielono odpowiedzi poniżej, zanim oznaczono je jako duplikat. Poniższe odpowiedzi są znacznie lepsze niż połączone pytanie, na które udzielono odpowiedzi. Ponadto pytanie jest inne, pytanie to wymaga opróżnienia katalogu, a nie usunięcia.
Bart Burg

1
Tak, to jest inne pytanie, które wyciągnęło różne odpowiedzi. Nie powinien być oznaczony jako duplikat.
Daniel Bingham

Odpowiedzi:


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

Jeśli chcesz usunąć „ukryte” pliki, takie jak .htaccess, musisz użyć

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

4
Istnieje również DirectoryIterator lub DirectoryRecursiveIterator.
Eugene

6
Chociaż jest to oczywiste, wspomnę, że na przykład „ścieżka / do / temp / *. Txt” usunie tylko pliki txt i tak dalej.
Tertium

Czy to działa również w przypadku ścieżek względnych? Powiedzmy, że pełna ścieżka to „/ var / www / html / folder_and_files_to_delete /” A skrypt usuwania jest umieszczony w „/var/www/html/delete_folders_and_files.php”. Czy mogę po prostu potraktować „folder_i_plików_do_kasowania” jako ścieżkę?
yoano

1
@yoano tak, na pewno, o ile ścieżka względna jest poprawna.
Floern

Czy glob jest w porządku, jeśli katalog zawiera dziesiątki tysięcy lub setki tysięcy plików?
Dave Heq,

260

Jeśli chcesz usunąć wszystko z folderu (w tym podfolderów) korzystać z tej kombinacji array_map, unlinka glob:

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

To wywołanie może również obsługiwać puste katalogi (dzięki za wskazówkę, @mojuba!)


33
Najlepsza odpowiedź, dzięki. Aby uniknąć powiadomień, zrobiłbym to również glob("...") ?: [](PHP 5.4+), ponieważ glob()zwraca pusty katalog false.
mojuba

14
Usuwa wszystkie pliki w bieżącym folderze, ale zwraca ostrzeżenie dla podfolderów i nie usuwa ich.
Key-Six

2
Łącząc odpowiedzi Stichozy i mojuba:array_map('unlink', ( glob( "path/to/temp/*" ) ? glob( "path/to/temp/*" ) : array() ) );
Ewout,

7
@Ewout: Nawet jeśli połączymy odpowiedź Stichozy i Moujuby, gdy twój dar zwraca to samo ostrzeżenie dla podfolderów i nie usuwa ich
Sulthan Allaudeen

3
Niestety nie usuwa to podfolderów.
tmarois

92

Oto bardziej nowoczesne podejście przy użyciu Standardowej Biblioteki PHP (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
Działa to ładnie, gdy nie masz dostępu do SSH, a FTP zajmuje dosłownie godziny rekurencyjne usuwanie wielu plików i folderów ... za pomocą tych linii usunąłem 35000 plików w mniej niż 3 sekundy!
guari

Dla użytkowników PHP 7.1: $ file-> getRealPath () musi być użyte zamiast $ file. W przeciwnym razie PHP wyświetli błąd informujący, że unlink wymaga ścieżki, a nie wystąpienia SplFileInfo.
KeineMaster,

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

powinien być rozłączony ('/ path / to / directory /'.$ fileInfo-> getFilename ()); ponieważ unlink przyjmuje ścieżkę. Dobra odpowiedź.
Vic

8
Możesz nawet zrobić rozłączenie ($ fileInfo-> getPathname ()); co dałoby ci pełną ścieżkę do pliku. php.net/manual/en/directoryiterator.getpathname.php
Josh Holloway

Czy „DirectoryIterator” również nie przechodzi do podkatalogów? Jeśli tak, „rozłącz” wygeneruje ostrzeżenie w takich przypadkach. Czy treść pętli nie powinna wyglądać bardziej jak w odpowiedzi Yamiko i sprawdzać każdy wpis, czy jest to plik przed wywołaniem „unlink”?
Andreas Linnert

19

Ten kod z 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

Zobacz readdir i odłącz .

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

Zakładając, że masz folder z DUŻĄ liczbą plików, które je wszystkie odczytują, a następnie usuwanie w dwóch krokach nie jest tak skuteczne. Uważam, że najbardziej skutecznym sposobem usuwania plików jest po prostu użycie polecenia systemowego.

Na przykład w systemie Linux używam:

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

Lub to, jeśli chcesz usunąć rekurencyjne bez potrzeby pisania funkcji rekurencyjnej

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

te same dokładne polecenia istnieją dla każdego systemu operacyjnego obsługiwanego przez PHP. Pamiętaj, że jest to WYDAJNY sposób usuwania plików. $ absolutPathToFolder MUSI być sprawdzony i zabezpieczony przed uruchomieniem tego kodu, a uprawnienia muszą zostać przyznane.


2
Niebezpieczne przy użyciu tej metody, jeśli $absolutePatToFolderkiedykolwiek jest puste
Lawrence Cherone

@LawrenceCherone Czy inne alternatywy są bardziej bezpieczne?
robsch

3
@LawrenceCherone Mam nadzieję, że w dzisiejszych czasach nikt nie używa php z uprawnieniami roota. Mówiąc poważnie, oczekuję, że dane wejściowe będą „bezpieczne”, ponieważ wszystkie powyższe funkcje.
Dario Corno,

Najczęściej wybierane rozwiązania nie działają w środowiskach programistycznych, w których www lub www-data nie jest właścicielem. Administrator serwera musi upewnić się, że są ustawione odpowiednie prawa do folderu. exec jest nieocenionym narzędziem do wykonywania zadań, z wielką mocą itp. stackoverflow.com/a/2765171/418974
Christian Bonato

@LawrenceCherone masz całkowitą rację, moja odpowiedź była przeznaczona dla bardzo konkretnej sytuacji, tylko ze względu na wydajność. Zmodyfikowałem moją odpowiedź zgodnie z twoimi notatkami.
Dario Corno,


4

Inne rozwiązanie: ta klasa usuwa wszystkie pliki, podkatalogi i pliki z podkatalogów.

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

Funkcja unlinkr rekurencyjnie usuwa wszystkie foldery i pliki w podanej ścieżce, upewniając się, że nie usuwa samego skryptu.

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

jeśli chcesz usunąć wszystkie pliki i foldery, w których umieścisz ten skrypt, wywołaj go w następujący sposób

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

jeśli chcesz po prostu usunąć tylko pliki php, nazwij to w następujący sposób

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

możesz również użyć dowolnej innej ścieżki, aby usunąć pliki

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

Spowoduje to usunięcie wszystkich plików w katalogu home / user / temp.


3

Wysłano klasę obsługi plików i folderów ogólnego przeznaczenia do kopiowania, przenoszenia, usuwania, obliczania rozmiaru itp., Która może obsługiwać pojedynczy plik lub zestaw folderów.

https://gist.github.com/4689551

Używać:

Aby skopiować (lub przenieść) pojedynczy plik lub zestaw folderów / plików:

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

Usuń pojedynczy plik lub wszystkie pliki i foldery ze ścieżki:

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

Oblicz rozmiar pojedynczego pliku lub zestawu plików w zestawie folderów:

$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

Dla mnie rozwiązanie, które readdirbyło najlepsze, działało jak urok. W globprzypadku niektórych scenariuszy funkcja nie działała.

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

Zaktualizowałem odpowiedź @Stichoza, aby usunąć pliki przez podfoldery.

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

Istnieje pakiet o nazwie „Pusheh”. Za jego pomocą możesz wyczyścić katalog lub całkowicie go usunąć ( link Github ). Jest również dostępny na Packagist .

Na przykład, jeśli chcesz wyczyścić Tempkatalog, możesz:

Pusheh::clearDir("Temp");

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

Jeśli jesteś zainteresowany, zobacz wiki .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.