1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

[PHP]Nao gosto da minha função recursiva

Discussão em 'Web Development' iniciada por Armadillo, 2 de Janeiro de 2008. (Respostas: 23; Visualizações: 2126)

  1. Armadillo

    Armadillo Folding Member

    Já me mandou o serviço do apache abaixo umas nao-sei-quantas vezes e é lento que nem um caracol!
    Sugestoes para melhorar o meu script serao muito bem aceites!
    O que o meu codigo faz é devolver num vector unidimensional (requisito imprescindivel) todas as pastas existentes, dado um caminho inicial.

    PHP:
    <?php


    //exemplo de utilizacao da funcao
    //Para devolver todos os ficheiros e directorios num vector, dado um caminho
    // $filestructure = pesquisa_dir_recursivamente('caminho/a/pesquisar');
     
    //Para devolver todos os ficheiros  e directorios num vector, dado um caminho e uma extensao de ficheiro
    // $filestructure = pesquisa_dir_recursivamente('caminho/a/pesquisar', 'extensao'); 

     
    function pesquisa_dir_recursivamente($directorio$filtro=FALSE)
     {

    if(
    substr($directorio,-1) == '/')                                                //se o caminho tiver no fim uma barra
        
    {
            
    $directorio substr($directorio,0,-1);                                    // removemos.
        
    }

        
    if(!
    file_exists($directorio) || !is_dir($directorio))                            //se caminho for invalido  ou nao for um directorio...
        
    {
        return 
    FALSE;                                                                // ... retorna FALSE e sai da funcao
    }elseif(is_readable($directorio))                                                // ... se o caminho eh valido
        
    {
         
    $directorio_list opendir($directorio);                                    // abrimos o directorio
         
    while (FALSE !== ($ficheiro readdir($directorio_list)))                    // e procuramos items nele
         
    {
            if(
    $ficheiro != '.' && $ficheiro != '..')                                //se apontador de ficheiro nao for o actual directorio ou o directorio pai
            
    {
                
    $path $directorio.'/'.$ficheiro;                                    //construimos o novo caminho a pesquisar
                
    if(is_readable($path))                                                // se o caminho for valido
            
    {
                    
    $subdirs explode('/',$path);                                     // dividimos o novo caminho em directorios 
                    
    if(is_dir($path))                                                // se o novo caminho for um directorio
                         
    {
                         
    $directorio_tree[] = array($path,
                        
    pesquisa_dir_recursivamente($path$filtro));                // pesquisamos o novo caminho chamando esta funcao (recursividade)
                        
                    
    }
                }
               }
         }

        
    closedir($directorio_list);                                                 // fechar directorio
        
    return $directorio_tree;                                                    // retornar a lista de ficheiros
        
    }
    else
        {                                                                            
    // se o caminho nao for valido
         
    return FALSE;                                                                // ... retorna FALSE
        
    }
    }
        

    //testando funcoes

    function listaArray(&$item2$key)
    {

        global 
    $pastas;
        
    //echo "$item2<br>\n";
        
        
    if (!is_array($item2) && !is_null($item2))        //se nao for um vector
            
    {
            
    $pastas[]=$item2;                            //adiciona item ao vector 
            
    }
        
    array_walk($item2'listaArray');
    }


    $array pesquisa_dir_recursivamente('..\..');     //ler disco em busca de dirs
    array_walk($array'listaArray');                //retornar apenas as dirs

    $pastas=array_unique($pastas);                    //remover possiveis duplicacoes nas pastas(caso dos null)
    sort($pastas);
    echo 
    '<pre>';
    var_dump ($pastas);
    echo 
    '</pre>';

    Também nao consigo fazer uma pesquisa por um caminho do tipo "c:\programas", apenas "..\..\".
    Acho que o codigo esta bem comentado. Se tiverem duvidas em relação a alguma coisa, buzinem
    Ja agora, estou a usar a versao 4.4.3 do PHP.
    :msmiley1:
     
    Última edição pelo moderador: 2 de Janeiro de 2008
  2. inginheiiro

    inginheiiro Power Member

    funcões recursivas em web scripting

    não sei o estas a fazer concretamente, mas não é aconselhavel faze-lo (recursivamente ou não) nesse modelo especifico.

    existem muitas "variaveis" não deterministicas neste problema/plataforma que inviabilizam uma solução recursiva optima e funcional...


    Alternativas:

    1. Lês um nivel apenas e permites ao utilizador inter-agir , lendo 1 nivel de cada vez quando se selecciona uma pasta. podes/deves usar ajax para isso. (+- como as tree views)

    2. Fazes um webservice que implemente a tua função recursiva, e chama-lo asyncronamente do php. (já não mexo em php à algum tempo mas penso já ser possivel faze-lo em php)

    3. Fazes uma função/webservice que te retorna o nivel que desejas apenas, e implementas a lógica/recursividade usando ajax (javascript) :)


    ainda assim optava pela solução 1 ou 3.

    /ing
     
  3. Armadillo

    Armadillo Folding Member

    Pois é, so que isto é para ser implementado num sistema passivo, ou seja, nao vai haver interacção com o utilizador.
    Em relação aos niveis, torna-se-me impossivel de saber quantos niveis é que terei que ler, visto que este script vai correr de forma autónoma, num servidor ao qual nao tenho acesso directo e o meu script tem que ser suficientemente polivalente para procurar um determinado ficheiro numa localização qualquer.
    Em relação ao ajax, penso que só é possivel utiliza-lo com um webbrowser (não tenho a certeza), coisa que nao vai acontecer no meu caso (executo os php atraves do wget despolotado através do cron) e tambem porque, na minha opiniao, nao se coaduna com o espirito do meu projecto (carago, isto ficou caro em palavras! ;)).

    Sei que sao muitas limitações que imponho mas tem que ser executado desta forma.
    Ainda assim, agradeço a vossa ajuda.

    Obrigado.
     
  4. inginheiiro

    inginheiiro Power Member

    cron

    se o vais chamar do cron, pq usas Php?

    pq não fazes um script em perl/java etc que faça isso e retorne o respectivo XML ?

    neste caso/modelo já te aconselharia o uso de recursividade .

    /ing
     
  5. Armadillo

    Armadillo Folding Member

    1. nao fui eu que decidi, ja estava implementado parte do sistema em php e para a integração/interacção entre os varios modulos ser mais rapida optou-se por continuar a usar php.

    2. nao sei se o nosso servidor corre java ou perl (riam-se de mim!, eu sou amigo do bill, que é que se há-de fazer?).
    Tem uma distro de linux altamente modificada e nao convem instalarmos mais nada a nao ser com o que ja vem de origem (questao de compatibilidade com futuras actualizações do fabricante da maquina/os). Apenas sei que aquela coisa corre php 4.4.3.
    Tenho acesso ao servidor muito limitado, nao posso andar a inventar pq senao tadinho do programador... Tou tipo do Liedson, parece um quartel general ;)
     
  6. inginheiiro

    inginheiiro Power Member

    :),

    posso ainda sugerir o uso de bash.

    echo "<pre>" >out.txt
    find /home -name '*' >> out.txt
    echo "</pre>" >>out.txt



    sempre resulta , depois só tens que tratar a listagem :)

    /ing
     
  7. Armadillo

    Armadillo Folding Member

    vais-me desculpar, mas executo isso no php? como se fosse na command line (sei que é possivel, nao me lembro é da sintax)?

    edit:
    ou seja:
    PHP:
    $resultCommandLine=executacommandlinefind /home -name '*');
    $tmp explode(char(13), $resultCommandLine);
    //... etc bla-bla-bla
    humm?
     
    Última edição pelo moderador: 2 de Janeiro de 2008
  8. slack_guy

    slack_guy Power Member

    epa.. um servidor *NIX sem Perl é como um jardim sem flores! :-)

    Vejo aqui uma excelente oportunidade para te debruçares sobre o Perl ;-) isso que pretendes fazes em 6 (vá lá... 7) linhas de código.
     
  9. inginheiiro

    inginheiiro Power Member

    Se quiseres podes chamar atraves do php, mas tava a pensar no seguinte:

    fazes um ficheiro bash(usa o chmod para tornar o ficheiro executavel) em linux .
    depois chama-lo a partir do cron, e este gera um ficheiro ou.txt
    depois podes ler esse fich do php.


    se o ficheiro se chamar script.bash , chama-lo da seguinte forma: ./script.bash /home

    referencias bash http://www.linux.org/docs/ldp/howto/Bash-Prog-Intro-HOWTO.html#toc5
    referencias do find http://www.linuxdevcenter.com/linux/cmd/cmd.csp?path=f/find


    #!/bin/bash
    echo "<pre>" >out.txt
    find $1 -name '*' >> out.txt
    echo "</pre>" >>out.txt


    /ing
     
  10. Armadillo

    Armadillo Folding Member

    Como ja disse:

    Tenho acesso ao servidor muito limitado, nao posso andar a inventar pq senao tadinho do programador... Tou tipo do Liedson, parece um quartel general ;)

    :iconlock:riam-se riam-se, oxalá nuca vos aconteça a vós, nem consigo imprimir um naco de codigo!:005:

    vamos la malta, tem que ser em php, nada de brainfuck ou perl.:lol:
    nao me abandonem...

    eh pá, isso parece muita volta so pra fazer um list aos dirs existentes num outro dir.
    e depois, nao me parece muito pratico ter um bash a ser chamado pelo cron, que irá gerar um ficheiro, e depois despolotar o script principal (e se o 2º começa antes do 1º acabar, sabe-se lá, os servidares as vezes ficam tolos!).

    Alguem se lembra do comando para executar um comando na shell atraves do php?
    Acham esta a solução mais limpinha e simples de fazer o que eu quero em PHP?

    Obrigado a todos.
     
    Última edição pelo moderador: 2 de Janeiro de 2008
  11. slack_guy

    slack_guy Power Member

    mas explica lá em duas linhas qual é o INPUT e qual é o OUTPUT do script?
     
  12. Armadillo

    Armadillo Folding Member

    basicamente tenho que pesquisar uns ficheiros (nao sei quais, por isso pode ir por parametro a extensao ou localizo-os posteriormente sabendo em que directórios tenho que pesquisar) que estao localizados sabe-se lá onde e importar o conteudo desses ficheiros para a bd em mysql.
    Posso ter que lidar com uns valentes milhares ou centenas de milhares desses ficheiros e por uma arvore de directorios manhosa.

    PS:Slack_guy, tu deves pensar que eu tenho ideias malucas (já me ajudaste em algumas), mas nao sou eu, ve na minha assinatura o link 'isto é a minha vida...'. É a pura verdade

    Obrigado

     
    Última edição: 3 de Janeiro de 2008
  13. K0mA

    K0mA Power Member

    Onde é que eu já vi isto...

    Todas a soluções de listar ficheiros numa pasta e sub-pastas que vi até agora recorriam a recursividade...
    Poderás é tentar separar as coisas para não sobrecarregar o sistema.

    Função 1 - obter o caminho de todas as pastas e subpastas > $caminhos = array()
    Função 2- For each $caminhos as $caminho > $ficheiros = array()
    ...

    EDITADO: ou então visitas este sitezeco.
     
    Última edição: 2 de Janeiro de 2008
  14. slack_guy

    slack_guy Power Member

    isso quer dizer que tens de abrir, ler e procurar por determinado padrão dentro dos ficheiros? ou é pelos nomes dos ficheiros?

    Será tipo isto?
    Dada a pasta /home/slack como ponto de partida, percorre todos os ficheiros e pastas e devolve o conteúdo de todos os ficheiros com extensão 'txt' ou 'dat' que contenham a expressão 'EXPRESSAO'.

    Se é isto, a única coisa que me falta saber é... em que formato queres o output? Aqui tens duas opções:
    1) são devolvidos os nomes (e respectivos caminhos) dos ficheiros;
    2) é criado um ficheiro com determinadas marcas (XML?) com todos os conteúdos dos ficheiros encontrados. É devolvido o nome e o caminho deste ficheiro. O teu programa encarrega-se de fazer o parse do ficheiro.
     
  15. Tyran

    Tyran Power Member

    Para correres comandos, vê aqui
    tem lá tmb como correres os scripts

    cumpzz
     
  16. Armadillo

    Armadillo Folding Member

    Nao posso usar scandir porque estou a usar a versao 4.4.3 do PHP.



    Slack_guy, apenas preciso da localização dos ficheiros definidos por uma prefixo no nome do ficheiro (ex: c:\data\export\2001\12\FACT_xxxx_xxxxxx.YYY | c:\data\export\2002\1\1233\AST_xxxxxx.YYY). Para processar o conteudo dos ficheiros, nao preciso de nada, pois ja esta feito há uns aninhos.

    Em relação ao output preciso de um vector unidimensional com o nome e caminho dos ficheiros.

    Para simplificar, e ja tendo uma função que pesquisa os ficheiros dado um determinado prefixo e num determindado directorio, neste momento apenas preciso dos directorios existentes num determinado caminho de origem num vector unidimensional.

    Espero ter sido claro e explicito,
    Obrigado pessoal pela ajuda.
     
    Última edição: 3 de Janeiro de 2008
  17. Armadillo

    Armadillo Folding Member

    ainda continuo com o problema dos caminhos dos directório...
    Alguma alma caridosa que me ajude :confused:
     
  18. AragTey

    AragTey Power Member

    Boas eu não sei nada de PHP....apenas tou a ver o algoritimo com base no que sei de C, mas esta parte aqui


    Código:
    $subdirs = explode('/',$path);        // dividimos o novo caminho em directorios 
    if(is_dir($path))                          // se o novo caminho for um directorio
    {
      $directorio_tree[] = array($path,
      pesquisa_dir_recursivamente($path, $filtro));               
    }
    
    nao percebo o que faz o explode, mas não é $subdirs que fica com a path do novo directorio?
     
  19. Armadillo

    Armadillo Folding Member

    o que o explode faz é dividir uma string num array de strings, sendo dado um caracter "divisor"
    Acho que essa linha se pode ignorar. (vou comentar essa linha)

    É assim, a função funciona lindamente, excepto com com caminhos do tipo /opt/site/_Site1 ou c:\programas\site\_Site1\
    , ate agora só consegui por isto a funcionar com caminhos do tipo .. e ../..

    Gracias
     
  20. AragTey

    AragTey Power Member

    $directorio_tree[] = array($path, pesquisa_dir_recursivamente($path, $filtro));

    o que acontece quanto é returnado o valor FALSE na funcao? E se a mesma e returnar um array de chars?
     

Partilhar esta Página