Script PHP para percorrer todos os arquivos em um diretório?

131

Estou procurando um script PHP que percorre todos os arquivos em um diretório para que eu possa fazer coisas com o nome do arquivo, como formatar, imprimir ou adicioná-lo a um link. Gostaria de poder classificar os arquivos por nome, tipo ou data criada / adicionada / modificada. (Pense no diretório "índice" sofisticado.) Também gostaria de poder adicionar exclusões à lista de arquivos, como o próprio script ou outros arquivos do "sistema". (Como os diretórios " .e ..".)

Sendo que eu gostaria de modificar o script, estou mais interessado em examinar os documentos PHP e aprender a escrever um. Dito isto, se houver scripts, tutoriais e outros itens existentes, entre em contato.

Moshe
fonte

Respostas:

245

Você pode usar o DirectoryIterator . Exemplo do Manual do php:

<?php
$dir = new DirectoryIterator(dirname(__FILE__));
foreach ($dir as $fileinfo) {
    if (!$fileinfo->isDot()) {
        var_dump($fileinfo->getFilename());
    }
}
?>
Morfildur
fonte
3
Nota: muitos servidores não possuem o SPL instalado; portanto, você não poderá usar a classe DirectoryIterator (veja minha postagem alternativa abaixo). Use isso se puder!
NexusRex
4
Nota [2]: Certifique-se de entender que a dirname()função acima obterá a pasta pai de qualquer caminho que você colocar lá. No meu caso, assumi que o dirname era um wrapper para o nome do diretório / caminho, portanto não era necessário.
willdanceforfun
Além disso, se dirname for um sistema de arquivos grande, problemas com memória são evidentes. No meu caso, com 1 milhão de arquivos, o aplicativo precisa de ~ 512M de memória ram no memory_limit.
abkrim
1
Se você precisa do caminho completo como /home/examples/banana.jpgo uso$fileinfo->getPathname()
mgutt
Você pode usar $ fileinfo-> isDir () para Ação Evite em diretórios!
LeChatNoir
44

Se você não tem acesso à classe DirectoryIterator, tente o seguinte:

<?php
$path = "/path/to/files";

if ($handle = opendir($path)) {
    while (false !== ($file = readdir($handle))) {
        if ('.' === $file) continue;
        if ('..' === $file) continue;

        // do something with the file
    }
    closedir($handle);
}
?>
NexusRex
fonte
4
Você pode citar uma situação em que não teria acesso a ela?
Jochem Kuijpers
12
Muitos aplicativos herdados usam o PHP 4, que não tem acesso ao DirectoryIterator.
Joseph Callaars
1
Por quê '.' === $ arquivo? Isto não é Java.
Dave Heq
2
Dave ... Não, ele corresponde aos pontos e não continua se não corresponder no PHP. Procure a diferença entre == e ===.
JSG
22

Use a scandir()função:

<?php
    $directory = '/path/to/files';

    if (!is_dir($directory)) {
        exit('Invalid diretory path');
    }

    $files = array();
    foreach (scandir($directory) as $file) {
        if ($file !== '.' && $file !== '..') {
            $files[] = $file;
        }
    }

    var_dump($files);
?>
ChorData
fonte
18

Você também pode fazer uso FilesystemIterator. Exige ainda menos código DirectoryIteratore remove .e automaticamente ...

// Let's traverse the images directory
$fileSystemIterator = new FilesystemIterator('images');

$entries = array();
foreach ($fileSystemIterator as $fileInfo){
    $entries[] = $fileInfo->getFilename();
}

var_dump($entries);

//OUTPUT
object(FilesystemIterator)[1]

array (size=14)
  0 => string 'aa[1].jpg' (length=9)
  1 => string 'Chrysanthemum.jpg' (length=17)
  2 => string 'Desert.jpg' (length=10)
  3 => string 'giphy_billclinton_sad.gif' (length=25)
  4 => string 'giphy_shut_your.gif' (length=19)
  5 => string 'Hydrangeas.jpg' (length=14)
  6 => string 'Jellyfish.jpg' (length=13)
  7 => string 'Koala.jpg' (length=9)
  8 => string 'Lighthouse.jpg' (length=14)
  9 => string 'Penguins.jpg' (length=12)
  10 => string 'pnggrad16rgb.png' (length=16)
  11 => string 'pnggrad16rgba.png' (length=17)
  12 => string 'pnggradHDrgba.png' (length=17)
  13 => string 'Tulips.jpg' (length=10)

Link: http://php.net/manual/en/class.filesystemiterator.php

Julian
fonte
5

Você pode usar esse código para percorrer um diretório recursivamente :

$path = "/home/myhome";
$rdi = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_PATHNAME);
foreach (new RecursiveIteratorIterator($rdi, RecursiveIteratorIterator::SELF_FIRST) as $file => $info) {
    echo $file."\n";
}
GameScripting
fonte
2

glob () possui provisões para classificação e correspondência de padrões. Como o valor de retorno é uma matriz, você pode fazer quase tudo o que precisa.

bcosca
fonte
1
Isso é bom, a menos que você esteja lidando com muitos arquivos ...> 10.000. Você ficará sem memória.
NexusRex
@NexusRex: Você não deve estar lendo 10.000 registros de um banco de dados de qualquer um, mas que está fora de alcance, tanto quanto a questão está em causa
bcosca
Acordado! Se estiver lendo de um banco de dados, você pode paginar com "limite" - sem essa sorte quando tiver um diretório com 5 milhões de arquivos XML para percorrer.
NexusRex
Existe o SPL GlobIterator.
Przemo_li 5/09
2

Para garantir a integridade (já que essa parece ser uma página de alto tráfego), não vamos esquecer a boa e antiga dir()função :

$entries = [];
$d = dir("/"); // dir to scan
while (false !== ($entry = $d->read())) { // mind the strict bool check!
    if ($entry[0] == '.') continue; // ignore anything starting with a dot
    $entries[] = $entry;
}
$d->close();
sort($entries); // or whatever desired

print_r($entries);
Sz.
fonte