[PHP] Zoeken in folder & subfolders

Pagina: 1
Acties:
  • 335 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

  • magiel
  • Registratie: Januari 2005
  • Laatst online: 20-09 08:19
Beste medetweakers :)

Ben voor m`n stage een script aan het schrijven, waarmee bestanden geupload worden in de bijbehorende map op de fileserver. Momenteel heb ik dit als volgt werkend:
bestand word opgeslagen in de map
\\$klantdata\'$1eletterklantnaam'\'$klantnaam-$debnr'\'$merk'\'$type'.
Indien nodig, worden er mappen aangemaakt.
Dit gaat allemaal goed. Maar er is al een bestaande mappenstructuur die iets anders is opgebouwd, namelijk \\klantdata\'$merk'\'$1eletterklantnaam'\'$klantnaam'\'$type'.

Helaas komen $merk uit de 1e regel en $merk uit de 2e regel maar in ~1 van de 100 gevallen overheen, dus hier valt geen koppeling op te maken, zelfde geldt voor $type.

Ook is het niet mogelijk om een al bestaand $type te koppelen aan het bijbehorende $merk, dit is in de database nooit bijgehouden, en om nu nog dit voor 20.000+ types te doen is onbegonnen werk...

Maar nou wil ik dus in \\klantdata\'$merk' en submappen zoeken naar $klantnaam, en dan in de directory-stream naar deze map bladeren, om hier het bestand te uploaden.

Als de directory dan niet gevonden wordt, moet de functie die ik nu al heb in werking treden.

Aangezien het gaat om bestanden op een remote server tov de webserver, is de functie "glob()" niet te gebruiken. Scandir() zoekt alleen in de huidige map, en niet in de submappen.

Ik zat al te denken om met scandir een array van alle submappen op te halen en deze dan in een foreachlus te gooien, waarin hij per map weer scandir() doet en een lijst met mappen tevoorschijn tovert en daar weer hetzelfde truucje mee uithaalt, totdat er een mapnaam voldoet aan de zoekwaarde, maar ik vraag me af of dit wel zo efficient is ?

Heel in het kort, zoals een collega het zei:
alle shit in een dir en de subdirs en dan zoeken?

[ Voor 4% gewijzigd door magiel op 16-11-2007 14:25 ]

Ik wil het er _niet_ over hebben.


Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
Ik zat al te denken om met scandir een array van alle submappen op te halen en deze dan in een foreachlus te gooien, waarin hij per map weer scandir() doet en een lijst met mappen tevoorschijn tovert en daar weer hetzelfde truucje mee uithaalt, totdat er een mapnaam voldoet aan de zoekwaarde, maar ik vraag me af of dit wel zo efficient is ?
Veel efficienter wordt het niet, dit is eigenlijk de enige manier waarmee je dit kan doen. Je maakt een functie die bestanden uit een map in een lijst zet, en indien deze functie nog een map vindt, roept hij zichzelf weer aan op die map. Goegel ook eens naar 'recursieve functie' of kijk op Wikipedia, die vindt wel meer van dit soort grappen.

Hier is een voorbeeld in Java, bijvoorbeeld:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// geeft een lijst van strings terug

    public List <String> getFilePaths(File directory) throws IOException {
     
        // lijst in functie om alle bestanden op te slaan in de huidige map.
        List <String> paths = new ArrayList <String>();
 
        // maakt een lijst van bestanden, de filter zorgt ervoor dat alleen bestanden met een
        // bepaalde extensie en mappen tevoorschijn komen.
        String[] contents = directory.list(getFilter());

        // blader door de bestanden in de map
        for (String path : contents) {
            path = directory.getCanonicalPath() + File.separatorChar + path;

            File current = new File(path);

            // roep de functie recursief aan indien het huidige bestand een map is
            if (current.isDirectory()) {
                paths.addAll(getFilePaths(current));
            
            // zet gewoon het path naar het bestand in de lijst indien het een gewoon bestand is.
            } else {
                paths.add(current.getCanonicalPath());
            }
        }

        // geef de lijst van de map z'n bestanden plus de bestanden in de submappen terug.
        return paths;
    }


hele andere taal, maar het concept blijft hetzelfde - volgens mij zijn er genoeg voorbeelden voor dit in PHP op het internet te vinden.

[ Voor 3% gewijzigd door YopY op 16-11-2007 16:03 ]


Acties:
  • 0 Henk 'm!

  • Peedy
  • Registratie: Februari 2002
  • Laatst online: 06-11-2024
Hier een PHP scriptje om bovenstaande te doen:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
        function dirList ($directory) 
        {
        if(file_exists($directory)) {
                $results = array();
                $handler = opendir($directory);
                while ($file = readdir($handler)) {
                    if ($file != '.' && $file != '..') $results[] = $file;
                    }
                closedir($handler);
                return $results;
            
            }
        }

Acties:
  • 0 Henk 'm!

  • HarmenM
  • Registratie: Juni 2001
  • Niet online
Recursief door directory's wandelen kan als volgt:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function listDir($path)
{
    $fileList = array();
    foreach(scandir($path) as $file)
    {
        $completePath = $path . "/" . $file;
        
        if($file == "." || $file == "..") {}
        else if(is_dir($completePath))
        {
            $fileList = array_merge(listDir($completePath), $fileList);
        }
        else
        {
            $fileList[] = $completePath;
        }
    }
    return $fileList;
}

Acties:
  • 0 Henk 'm!

  • ChessSpider
  • Registratie: Mei 2006
  • Laatst online: 01-08 19:01
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function listDir($path)
{
    foreach(scandir($path) as $file)
    {
        $completePath = $path . "/" . $file;
        
        if($file != "." && $file != "..") 
        {
            if(is_dir($completePath))
                $fileList = array_merge(listDir($completePath), $fileList);
            else
                $fileList[] = $completePath;
        }
    }
    return $fileList;
}


Korter... En verbeterd
klopt "$fileList = array_merge(listDir($completePath), $fileList);" trouwens wel?
lijkt mij dat dat
$fileList[] = array_merge(listDir($completePath), $fileList);
moet zijn..

[ Voor 10% gewijzigd door ChessSpider op 17-11-2007 14:21 . Reden: Verbeteringen toegevoegd, dank HarmenM :) ]


Acties:
  • 0 Henk 'm!

  • HarmenM
  • Registratie: Juni 2001
  • Niet online
ChessSpider schreef op zaterdag 17 november 2007 @ 13:20:
PHP:
1
2
3
4
5
6
7
function listDir($path, $fileList)
{
    if(!is_array($fileList))
        $fileList = Array();

    ....
}


Korter... En verbeterd
Waarom zou je $fileList als argument willen meegeven aan de functie? Het lijkt mij afdoende om per directory $fileList te vullen met alle bestanden die daarin staan en deze te retourneren. De enige informatie die relevant is, is het $path waarvan de bestanden moeten worden gelist.

Acties:
  • 0 Henk 'm!

  • ValHallASW
  • Registratie: Februari 2003
  • Niet online
Voor LaTeX-pakketjes wordt een file met daarin een ls -R-dump gebruikt; dan kan je dus gewoon zoeken in een textfile. Ik weet niet hoe mutatiegevoelig je klantenbestand is, maar als ik het goed begrijp is het puur voor gebruik van een oude structuur.

Overigens zou ik liever investeren in het nu goedzetten van 20000 entries dan het iedere keer scannen van een directory tree...

Acties:
  • 0 Henk 'm!

  • magiel
  • Registratie: Januari 2005
  • Laatst online: 20-09 08:19
Zie hierboven wel een paar dingen staan waar ik wat mee kan :) bedankt ;)

En de mutatiegevoeligheid van de huidige manier van werken is hoog, erg hoog :)
Is namelijk nog een andere user-end database die niet niet om te vormen is naar de nieuwe manier.

Dat geuploadde bestanden die niet in de oude structuur geplaatst kunnen worden, dan niet zichtbaar zijn in de huidige userend db, is niet zo erg...

Ik wil het er _niet_ over hebben.


Acties:
  • 0 Henk 'm!

  • ChessSpider
  • Registratie: Mei 2006
  • Laatst online: 01-08 19:01
HarmenM schreef op zaterdag 17 november 2007 @ 13:39:
[...]


Waarom zou je $fileList als argument willen meegeven aan de functie? Het lijkt mij afdoende om per directory $fileList te vullen met alle bestanden die daarin staan en deze te retourneren. De enige informatie die relevant is, is het $path waarvan de bestanden moeten worden gelist.
Mijn fout, ik zag de tweede paramter van array_merge als de tweede parameter van Listdir functie, die niet in de originele aanroep stond. Daarom ook de doorgestreepte tekst, was alleen vergeten om de andere veranderingen die ik gedaan heb ongedaan te maken.

Acties:
  • 0 Henk 'm!

  • remcotolsma
  • Registratie: December 2005
  • Laatst online: 08-09 11:11
(jarig!)
Recursief door directory's wandelen kan in PHP 5+ ook als volgt:

PHP:
1
2
3
4
$it = new RecursiveDirectoryIterator('klantdata');
foreach(new RecursiveIteratorIterator($it) as $file) {
  echo $file, '<br />';
}

Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
Ingebouwde OO-truukjes gebruiken is lame :p.

Ik weet echt niet meer wat er allemaal in PHP 5 mogelijk is, waarschijnlijk zijn er nog heel veel meer van dat soort dingen in PHP 5.

Acties:
  • 0 Henk 'm!

  • HarmenM
  • Registratie: Juni 2001
  • Niet online
Leuke benadering die remcotolsma aandraagt. Even opgezocht: Het is onderdeel van Standard PHP Library-extensie, en is standaard meegeleverd met PHP 5.

http://www.php.net/manual/en/ref.spl.php

Acties:
  • 0 Henk 'm!

  • FragFrog
  • Registratie: September 2001
  • Laatst online: 22:47
HarmenM schreef op zaterdag 17 november 2007 @ 16:55:
Leuke benadering die remcotolsma aandraagt. Even opgezocht: Het is onderdeel van Standard PHP Library-extensie, en is standaard meegeleverd met PHP 5.

http://www.php.net/manual/en/ref.spl.php
De documentatie ervan is echter summier at best. Zelf ook eens naar lopen kijken voor een pagehandler die recursief directories kon doorlopen op zoek naar templates om een pagemap te bouwen. Als je er wat meer mee wil is het in mijn ervaring sneller een classe (of functie natuurlijk) te schrijven die zichzelf aanroept. :)

* FragFrog vermoedt dat de hele recursieve class bende in PHP6 gewoon wel standaard wordt, tot die tijd schrijft'ie het liever zelf :)

[ Voor 9% gewijzigd door FragFrog op 17-11-2007 17:06 ]

[ Site ] [ twitch ] [ jijbuis ]


  • magiel
  • Registratie: Januari 2005
  • Laatst online: 20-09 08:19
remcotolsma schreef op zaterdag 17 november 2007 @ 15:18:
Recursief door directory's wandelen kan in PHP 5+ ook als volgt:

PHP:
1
2
3
4
$it = new RecursiveDirectoryIterator('klantdata');
foreach(new RecursiveIteratorIterator($it) as $file) {
  echo $file, '<br />';
}
Ziet er opzich wel mooi uit, en het zou ook kunnen werken. Alleen gaat het om duizenden mappen, en de server crasht al wanneer hij de klanten met de letter A nog niet eens heeft afgewerkt in de 1e $merk map.
We hebben de hele boel maar omgegooid, en gaan nu voor elke upload een mapje aan maken volgens de nieuwe structuur. Toch bedankt voor de input & het meedenken ;)

Ik wil het er _niet_ over hebben.

Pagina: 1