V 17. díle
jsme si ukázali jednoduché řešení pro výpis jediného adresáře. Jsou ale případy,
kdy potřebujeme mít přehled o kompletní adresářové struktuře. Tedy nejen obsah
jednoho konkrétního adresáře, ale i všech dalších adresářů v jeho podadresářích
až k tomu poslednímu.
Ukážeme si nejdříve cyklus, na kterém skript postavíme.
$i=0; $adr=opendir($pozice); while ($file = readdir($adr)) { if ($file!="."&&$file!="..") { $polozka[$i]['name']=$file; $polozka[$i]['pozi']=$pozice; $polozka[$i]['size']=filesize($pozice.$file); $polozka[$i]['time']=date("H:i:s d.m.Y",filemtime($pozice.$file)); if (is_dir($pozice.$file)) { $polozka[$i]['type']="dir"; $dir2handle[count($dir2handle)]=$pozice.$polozka[$i]['name']."/"; } else { $polozka[$i]['type']="file"; } $i++; } }
|
Hned na začátku operujeme s pomocnou proměnnou $i - ta se na konci cyklu vždy
zvýší o jedna ($i++) a později se stává identifikujícím prvkem pro pole $polozka.
Funkcí opendir() otevřeme pro zpracování adresář, k němuž je cesta uložena v
proměnné $pozice. Nyní while() při každém cyklu přiřazuje proměnné $file jednu
položku z tohoto adresáře. Podmínka if() je jasná - stejně jako při prohlížení
jednoho adresáře v 17. díle i zde odstraňujeme adresářové cesty na současný
adresář a adresář o jeden výše.
Následuje přiřazování různých vlastností vícerozměrnému poli (multidimensional
array) $polozka[][]. S jednoduchým polem jsme se již setkali. Je to vlastně
proměnná obsahující více informací najednou a přistupujeme k ní přes identifikátor
mezi hranatými závorkami. Vícerozměrná znamená, že se další informace skrývají
pod dalšími identifikátory v dalších hranatých závorkách. Pro názornost: pole
$polozka[0][name] je jméno souboru, který se načetl jako první (začíname jako
obvykle od nuly), $polozka[0][size] je velikost tohoto souboru. $polozka[1][pozi]
však už patří k souboru (či adresáři) dalšímu. Tímto způsobem získáme všechna
data dobře přístupná v jednom poli, protože $i se zvyšuje vždy po ukončení jednoho
celého cyklu (jinými slovy: až se dokončí všechny operace s jedním souborem
či adresářem).
Do $polozka[$i]['name'] se ukládá jméno dotyčného souboru (či adresáře), $polozka[$i]['pozi']
obsahuje jméno nadřazeného adresáře (to je důležité pro zjištění struktury a
jednotlivých vazeb souborů a adresářů mezi sebou), v $polozka[$i]['size'] se
pomocí funkce filesize() zjistí velikost souboru (u adresáře to bude vždy 0,
cesta k souboru je udána $pozice.$file, což je skutečná a úplná cesta k dotyčnému
souboru). Do $polozka[$i]['time'] se zapíše pomocí již známé funkce date() datum
poslední změny souboru (funkce filemtime()). Následuje podmínka, jež má za úkol
zjistit, zda-li je aktuálně zpracovávaná položka soubor či adresář. Podle výsledku
se poté poli $polozka[$i]['type'] přiřadí buď řetězec "file" nebo
"dir". Jestliže se jedná o adresář, uloží se kompletní cesta k němu
do pole $dir2handle[]. Jeho identifikátor vytvoříme tak, že sečteme počet jeho
identifikátorů (0,1,2,3,4 - počet 5) - pokud neobsahuje nic, začneme číslem
0. Tím velice jednoduše získáme identifikátor vždy o 1 větší než je ten poslední.
Tento cyklus je však funkční pozue pro jeden adresář. Abychom jej mohli použít
úplně pro všechny adresáře, musí se stále měnit $pozice a to do té doby, než
vyčerpáme všechny adresáře určené ke zpracování. Provedeme tedy následující:
function loop_dir($pozice) { GLOBAL $dir2handle, $polozka; $i=count($polozka); $adr=opendir($pozice); while ($file = readdir($adr)) { if ($file!="."&&$file!="..") { $polozka[$i]['name']=$file; $polozka[$i]['pozi']=$pozice; $polozka[$i]['size']=filesize($pozice.$file); $polozka[$i]['time']=date("H:i:s d.m.Y",filemtime($pozice.$file)); if (is_dir($pozice.$file)) { $polozka[$i]['type']="dir"; $dir2handle[count($dir2handle)]=$pozice.$polozka[$i]['name']."/"; } else { $polozka[$i]['type']="file"; } $i++; } } } $dir2handle[0]='./'; for($j=0;$j<(count($dir2handle));$j++) { loop_dir($dir2handle[$j); }
|
Cyklus jsme včlenili do námi definované funkce loop_dir(). Voláme ji v dalším
cyklu, for(). První cyklus probíhá následovně: pole $dir2handle[0] obsahuje
'./', tedy současný adresář. Cyklus for probíhá od 0 až do čísla menšího než
počet položek v poli $dir2handle[]. Tam máme nyní jednu položku, takže cyklus
by měl probehnout pouze jednou - pro nulu. Zavolá se funkce loop_dir(), která
předá proměnné $pozice obsah pole $dir2handle[0], tedy to './'. Jak už jsme
si říkali, z funkcí je omezen výstup proměnných, proto nastavujeme pomocí GLOBAL
tzv. globální proměnné, tedy ty, jež budeme moci využívat i mimo naši funkci.
Pomocné $i se poprvé skutečně přiřadí 0 (pole $polozka[] je zatím prázdné).
Dále se zpracuje současný adresář přesně tak, jak jsme si ukázali výše. Výstupem
jsou tedy pole $dir2handle[] a $polozka[][]. $dir2handle[] obsahuje všechny
adresáře, jež máme za úkol dále zpracovat a v $polozka[][] jsou úplně všechny
dosud získané informace o souborech a adresářích.
Tím jsme ovšem neskončili! Na konci cyklu for() se k pomocné proměnné $j přičetla
jednička ($j++). Kdyby se nic nezměnilo, cyklus by se ukončil, jenže pokud námi
zvolený adresář obsahoval další adresáře, jsou přeci v poli $dir2handle[], které
tedy změnilo počet svých položek a z toho důvodu se o ně navýšilo omezení tohoto
cyklu. Takže se funkci loop_dir() předá další adresář ke zpracování a tak to
bude pokračovat až do doby, kdy již nebudou žádné další adresáře k dispozici.
Vícerozměrné pole $polozka[][] se mezitím zaplní všemi adresáři a soubory, jež
těmito cykli prošly.
Půlka celého problému je za námi, nyní přejdeme k řešení problému, jak ta data
dostat v nějaké rozumné podobě na obrazovku.
sort ($dir2handle); for($i=0;$i<(count($dir2handle));$i++) { echo '<b><a name="'.$dir2handle[$i].'">'; echo $dir2handle[$i]."</a></b><br><blockquote>"; for($j=0;$j<(count($polozka));$j++) { if($polozka[$j]['pozi']==$dir2handle[$i]&&$polozka[$j]['type']=="dir") { echo '<a href="#'.$polozka[$j]['pozi']; echo $polozka[$j]['name'].'/">'; echo $polozka[$j]['name']."</a> (dir)<br>"; } } for($j=0;$j<(count($polozka));$j++) { if($polozka[$j]['pozi']==$dir2handle[$i]&&$polozka[$j]['type']=="file") { echo '<a href="'.$polozka[$j]['pozi']; echo $polozka[$j]['name'].'">'; echo $polozka[$j]['name']."</a> ("; echo $polozka[$j]['size']." B, "; echo $polozka[$j]['time'].")<br>"; } } echo "</blockquote>"; }
|
Nejprve se pomocí funkce sort() abecedně seřadí pole $dir2handle. Dále následují
dva do sebe vnořené cykly, jež mají za úkol porovnat nadřazené adresáře všech
položek s obsahem $dir2handle[] a podle toho je vypsat či nevypsat. Aby se od
sebe logicky oddělily adesáře a soubory, jsou v cyklu cykly dva, první pro adresáře,
druhý pro soubory. Vypsání jednotlivých části pole $polozka[][] a html tagy
pro vytvoření odkazů je už předpokládám jasné. Toto rozhodně není jediné možné
řešení problému, jistě vymyslíte lepší, nám ale zatím stačí.
Nyní si ukážeme celý zdrojový kód včetně zadávání cesty přes formulář a kontroly
správnosti zadání:
<html> <body> <form> <input type="text" name="cesta" value="<?= $cesta ?>"> <input type="submit"> </form> <? if (isset($cesta)) { if(is_dir($cesta)) { if(substr($cesta,-1)!="/") { $dir2handle[0]=$cesta."/"; } else { $dir2handle[0]=$cesta; } } else { echo "Zadaná cesta <b>$cesta</b> není platným adresářem<br>"; $dir2handle[0]='./'; } } else { $dir2handle[0]='./'; } function loop_dir($pozice) { GLOBAL $dir2handle, $polozka; $i=count($polozka); $adr=opendir($pozice); while ($file = readdir($adr)) { if ($file!="."&&$file!="..") { $polozka[$i]['name']=$file; $polozka[$i]['pozi']=$pozice; $polozka[$i]['size']=filesize($pozice.$file); $polozka[$i]['time']=date("H:i:s d.m.Y",filemtime($pozice.$file)); if (is_dir($pozice.$file)) { $polozka[$i]['type']="dir"; $dir2handle[count($dir2handle)]=$pozice.$polozka[$i]['name']."/"; } else { $polozka[$i]['type']="file"; } $i++; } } } for($i=0;$i<(count($dir2handle));$i++) { loop_dir($dir2handle[$i]); } sort ($dir2handle); for($i=0;$i<(count($dir2handle));$i++) { echo '<b><a name="'.$dir2handle[$i].'">'; echo $dir2handle[$i]."</a></b><br><blockquote>"; for($j=0;$j<(count($polozka));$j++) { if($polozka[$j]['pozi']==$dir2handle[$i]&&$polozka[$j]['type']=="dir") { echo '<a href="#'.$polozka[$j]['pozi']; echo $polozka[$j]['name'].'/">'; echo $polozka[$j]['name']."</a> (dir)<br>"; } } for($j=0;$j<(count($polozka));$j++) { if($polozka[$j]['pozi']==$dir2handle[$i]&&$polozka[$j]['type']=="file") { echo '<a href="'.$polozka[$j]['pozi']; echo $polozka[$j]['name'].'">'; echo $polozka[$j]['name']."</a> ("; echo $polozka[$j]['size']." B, "; echo $polozka[$j]['time'].")<br>"; } } echo "</blockquote>"; } ?> </body> </html>
|
Do budoucna bych chtěl napojit tento výpis adresářové struktury s nečím podobným
SiteMapperu ze 16.
dílu. Tím bychom dostali kromě informací o slepých odkazech také zprávu
o tom, na které soubory pro změnu žádný odkaz nevede.
Veselý Jan
|