Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: [PHP] "Etsii" tiedostoja

combo [04.01.2011 23:44:28]

#

Miten olisi helppo tapa toteuttaa PHP:lla, niin että etsitään määrätystä hakemistosta annetulla nimellä tiedostoja vaikka ne ovatkin eri muotoisia.

Esimerkki:

Jos on määritetty niin että etsitään tiedostoja, joissa on nimi "kissa", ja löydetään tiedosto kissa.avi. Sitten seuraavaksi on määritetty etsittäväksi koira ja löydetään koira.wmv. Eli tarkoitus on etsitä tiedostoja joissa on määritelty nimi, mutta tiedostopäätteellä ei ole väliä.

kissa.avi
koira.wmv

Metabolix [05.01.2011 00:11:33]

#

$sana = "kissa";
$lista = glob("*{$sana}*");

// Glob saattaa palauttaa arvon false, jos tiedostoja ei ole;
// yleensä tyhjä taulukko on hyödyllisempi.
if (empty($lista)) {
  $lista = array();
}

-tossu- [05.01.2011 00:16:59]

#

combo kirjoitti:

Miten olisi helppo tapa toteuttaa PHP:lla, niin että etsitään määrätystä hakemistosta annetulla nimellä tiedostoja vaikka ne ovatkin eri muotoisia.

Metabolix kertoikin jo, miten glob-funktiolla haetaan tiedostoja. Se ei kuitenkaan hae alikansioista, mutta kirjoitin lyhyen funktion, joka toimii rekursiivisesti. Siinä käytetään globaaleja muuttujia, mikä ei ole hyvän ohjelmointitavan mukaista, mutta sillä saavutettaneen pieni nopeusetu.
Edit: Ei enään globaaleja muuttujia ja nyt koodikin toimii kunnolla.

function etsi ($hak, $etsittava, &$tiedostot) {
	foreach (scandir ($hak) as $i) {
		if ($i != "." && $i != "..") {
			if (is_dir ("$hak/$i"))
				etsi ("$hak/$i", $etsittava, $tiedostot);
			elseif (fnmatch ($etsittava, $i))
				$tiedostot [] = "$hak/$i";
		}
	}
}
$t = array ();
etsi (".", "*.php", $t);
echo implode ("\n", $t);

Metabolix [05.01.2011 00:49:57]

#

-tossu-, globaalien muuttujien nopeusetu ei varmasti ole merkittävä, jos sellaista on lainkaan, ja lisäksi niistä seuraa merkittävää hämminkiä koodiin, joten kannattaa saman tien tehdä kunnolla. Funktiosi myös toimii väärin: palautetuista nimistä ei selviä, missä hakemistossa tiedostot ovat, ja hakukaan ei etene syvemmille tasoille, koska esim. hakemiston x/y sijaan yrität hakea suoraan hakemistosta y.

Oikeasti rekursiivinen haku toimisi esimerkiksi näin:

function etsi($hak, $etsittava = "*") {
	if (!is_dir($hak)) {
		return array();
	}
	$tiedostot = array();
	etsi__rek($hak, $etsittava, $tiedostot);
	return $tiedostot;
}
function etsi__rek($hak, $etsittava, &$tiedostot) {
	foreach (scandir($hak) as $nimi) {
		if ($nimi == "." || $nimi == "..") {
			continue;
		}
		if ($hak == ".") {
			$kokonimi = $nimi;
		} else {
			$kokonimi = "{$hak}/{$nimi}";
		}
		if (is_dir($kokonimi)) {
			etsi__rek($kokonimi, $etsittava, $tiedostot);
		} elseif (fnmatch($etsittava, $nimi)) {
			$tiedostot[] = $kokonimi;
		}
	}
}
$lista = etsi("hakemisto", "*kissa*");
echo htmlspecialchars(implode("\n", $lista). "\n");

Sitä paitsi kysyjä halusi etsiä "määrätystä hakemistosta" eli minun käsittääkseni vain juuri siitä eikä rekursiivisesti sen alta.

-tossu- [05.01.2011 01:02:52]

#

Metabolix kirjoitti:

-tossu-, globaalien muuttujien nopeusetu ei varmasti ole merkittävä, jos sellaista on lainkaan, ja lisäksi niistä seuraa merkittävää hämminkiä koodiin, joten kannattaa saman tien tehdä kunnolla. Funktiosi myös toimii väärin

Huomasin itsekin nuo virheet heti kun sanoit niistä. Ei kannata koodata yöllä väsyneenä, tai sitten koodi pitää ainakin testata kunnolla. Onneksi täällä on ihmisiä, jotka huomaavat viat. Taidan mennä nukkumaan ja jatkaa koodausta huomenna, ettei tule lisää samanlaisia idiootti-mokia.

tsuriga [05.01.2011 06:26:09]

#

Koodivinkit - rekursiivinen hakemistolistaus globeilla

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta