Pergunta sobre file, directory, php – PHP: Como posso pegar um único arquivo de um diretório sem escanear o diretório inteiro?

13

Eu tenho um diretório com 1,3 milhões de arquivos que eu preciso para mover para um banco de dados. Eu só preciso pegar um único nome de arquivo do diretório sem verificar o diretório inteiro. Não importa qual arquivo eu pego, pois vou apagá-lo quando terminar com ele e, em seguida, passar para o próximo. Isso é possível? Todos os exemplos que posso encontrar parecem varrer toda a lista de diretórios para uma matriz. Eu só preciso pegar um de cada vez para o processamento ... não 1,3 milhões de cada vez.

@ JonathanSampson Duvido que ele se importe com o nome do arquivo. Ele quer pegar qualquer arquivo, colocá-lo no banco de dados e passar para o próximo. Samy Dindane

Sua resposta

4   a resposta
5

é um arquivo:

foreach(new DirectoryIterator('.') as $file)
{
    if ($file->isFile()) {
        echo $file, "\n";
        break;
    }        
}

Isso também garante que seu código seja executado em algum outro comportamento do sistema de arquivos que o esperado.

VejoDirectoryIterator eSplFileInfo.

Sim está claro agora. Obrigado por explicar. skibulk
@skibulk: Não, não, itera sobre oDirectoryIterator que não é uma matriz, mas um objeto. Isso efetivamente impede o que você teme: uma matriz. hakre
@skibulk: Sim, você poderia pensar sobre isso de tal maneira. Mais precisamente, invocaDirectoryIterator::next(), isso é por contrato em PHP entreforeach e aIterador interface. Mais claro? hakre
Isso não carrega todo o conteúdo do diretório em uma matriz? É isso que o Kyle está tentando evitar. Isso pode fazer diferença quando você tem milhares de arquivos na pasta. skibulk
Legal. estou acostumado aforeachmatrizes. Então quandoforeach acessa o próximo índice doDirectoryIterator, na verdade, está invocando um método (IE getNextFile ()) em vez disso? Estranho. skibulk
0

isto:

criar função "pickfirst" com argumento 2 (endereço e modo dir ou arquivo?)

function pickfirst($address,$file) { // $file=false >> pick first dir , $file=true >> pick first file
$h = opendir($address);

     while (false !== ($entry = readdir($h))) {

          if($entry != '.' && $entry != '..' && ( ($file==false && !is_file($address.$entry)) || ($file==true && is_file($address.$entry)) )  )
          { return $entry; break; } 

} // end while
} // end function

se você quiser escolher o primeiro diretório no seu conjunto de endereços$file para falso e se você quiser escolher o primeiro arquivo no seu conjunto de endereços$file para verdade.

boa sorte :)

19

Isso deve servir:

<?php
$h = opendir('./'); //Open the current directory
while (false !== ($entry = readdir($h))) {
    if($entry != '.' && $entry != '..') { //Skips over . and ..
        echo $entry; //Do whatever you need to do with the file
        break; //Exit the loop so no more files are read
    }
}
?>

readdir

Retorna o nome da próxima entrada no diretório. As entradas são retornadas na ordem em que são armazenadas pelo sistema de arquivos.

Ainda assim, a sobrecarga poderia ser evitada (cada pequena ajuda) simplesmente executando duas chamadas parareaddir antes do loop, como. e.. são sempre as primeiras entradas. connec
@SamyDindane, Essa verificação não vai demorar muito, especialmente em comparação com a leitura do arquivo do disco e armazená-lo em um banco de dados ... Zombaya
Prefiro inserir '.and' .. 'no banco de dados do que a verificação 1.3M vezes. Samy Dindane
Este código tem um grande problema se uma entrada de diretório não for desejada, como outro diretório ou um link simbólico etc.melhor usar o iterador de diretórios padrão que fornece objetos splfileinfo. hakre
@Zombaya De fato, não leva tempo. Eu tentei no meu computador: levou 200ms para rodarif ($entry != '.' && $entry != '..') {} 1,3 milhões de vezes Surpreendente. Samy Dindane
2

readdir vai fazer o truque. Verifique o exemplo nessa página, mas em vez de fazer a chamada readdir no loop, faça isso uma vez. Você receberá o primeiro arquivo no diretório.

Nota: você pode obter ".", ".." e outras respostas semelhantes, dependendo do servidor, portanto, você pode querer pelo menos efetuar um loop até obter um arquivo válido.

Perguntas relacionadas