[PHP]Sortowanie plikow do folderow


(master of disaster) #1

Witam.

Od razu mówię, że zdaje sobie sprawę z tego że PHP nie jest językiem programowania przeznaczonym do tego typu rzeczy. Jednak z racji tego że go w miarę umiem muszę napisać na szybko w nim skrypt. Otóż zawartość katalogu o nazwie np. "kat" to foldery i pliki tekstowe. I teraz jeżeli plik zawiera nazwę jakiegoś z folderów to przenieś plik do tego folderu. Np. jeśli katalog nazywa się D4717-01D1RAD a są pliki o nazwie D4717-01D1RAD MIRROR.txt, D4717-01D1RAD SFSD.txt to żeby przeniósł je do tego katalogu(D4717-01D1RAD).

<?php

$katalog = 'kat';

$dir=opendir($katalog);


while($entry=readdir($dir)) {


///// co tutaj?


}

closedir($dir);

Pozdrawiam, i przepraszam za taką a nie inną forme wyjaśnienia problemu, ale godzina robi swoje :wink:


(Pablo_Wawa) #2

Ja bym sugerował utworzyć sobie dwie tablice: na foldery oraz pliki. I w tej pętli, coś ją napisał, dla każdego $entry rozpoznawać czy jest to plik czy katalog (funkcją is_dir(): http://www.php.net/manual/en/function.is-dir.php) i wstawiać do właściwej tablicy.

Potem należy przeglądnąć tablicę z plikami (w pętli) i dla każdego elementu wyszukiwać, czy nie zawiera on w sobie nazwy jakiegoś folderu (zakładam, że nazwy folderów nie zawierają się w sobie, tj. nie będzie DIRECT1122 oraz DIRECT11). Do wyszukiwania tego występowania proponuję napisać osobną funkcję (będzie wygodniej się nią w pętli posłużyć).

I ważne jest, czy pliki mają zawierać nazwę katalogu w dowolnym miejscu, czy patrząc od początku tej nazwy?


(master of disaster) #3

Dziękuje za odzew.

no właśnie są też i takie foldery, i co wtedy?

Tylko i wyłącznie od początku.

I w jaki sposób sprawdzić czy któryś element z tablicy pliki zawiera nazwe elementu z tablicy katalogi ?

@edit wymyslilem cos takiego:

<?php

$katalog = 'kat';

$dir=opendir($katalog);

$katalogi = array();

$pliki = array();

$x=0;

$y=0;

$z=0;


function funkcja($tablica_kat,$tablica_pliki,$liczba_plik) {

	$l=0;

	while($liczba_plik>$l) {

		if($tablica_kat !== '.' && $tablica_kat !== '..') {

			if(strstr($tablica_pliki[$l], $tablica_kat)!==False) {

				echo $tablica_kat.' zawiera wyraz '.$tablica_pliki[$l].'
';

			}

		}

		$l++;

	}

}


while ($entry=readdir($dir)) {

	if(is_dir($katalog.'/'.$entry)){

		$katalogi[$x] = $entry;

		$x++;

	}

	else {

		$pliki[$y] = $entry;

		$y++;

	}


}

closedir($dir);



while($x>$z){

	funkcja($katalogi[$z],$pliki,$y);

	$z++;

}


?>

chyba jest ok?


(Drobok) #4

function f($a){

  foreach($kat as $k){//lepsza opcja przejścia przez tablice

    if(strstr($a,$k)!='FALSE') $t=$k)//jeśli znajdziemy katalog zapisujemy go w zmiennej 

  }

  if(!empty($r)) copy($a,$t.'\'.$p);//interesuje nas ostatni katalog, jeśli coś znaleźliśmy to kopiujemy

}

foreach ($pl as $p) {

  f($p);//wywołujemy funkcje wg plików

}

Co do twojego przykładu, teoretycznie jest ok, ale nie spełnia wymagań dot. zadania. Tzn nie kopiuje plików, oraz wyświetla wszystko tzn v, v2, dla pliku zawierającego v2. Tak samo weź pod uwagę, że :

if($tablica_kat !== '.' && $tablica_kat !== '..') {

Lepiej zrobić podczas listowania (mniej razy sprawdzasz). Oraz zamiast i=0;while(sth){... i++;} lepiej sobie zrobić for :slight_smile: Nie musisz przekazywać tablic do funkcji.


(master of disaster) #5

Tak, funkcja rename to juz nie problem.

Dzięki Panowie za pomoc i rady. Można zamknąć.

Pozdrawiam


(Pablo_Wawa) #6

Dorzucę jeszcze coś od siebie - może się przyda:

  1. Zamiast takiej konstrukcji

    $katalogi[$x] = $entry;

    $x++;

można zastosować taką

$katalogi[] = $entry;

a rozmiar tablicy (liczbę jej elementów) - jeśli jest konieczna - policzyć na końcu

$x = count($katalogi);
  1. Jeśli nazwy folderów zawierają się częściowo w sobie (np. mamy takie: DIRECT1122, DIRECT112233 oraz DIRECT11), to co zrobić z plikiem DIRECT1122334455.txt? W zaprezentowanym przypadku trafi on albo do pierwszego (DIRECT1122), albo do ostatniego (DIRECT11) folderu - w obu przypadkach chyba błędnie, bo chcielibyśmy by trafił do "najdłużej dopasowanego". Wtedy należy skorzystać z wyrażenia regularnego i funkcji preg_match(), wyznaczać długość dopasowania i zapamiętywać maksimum (długość oraz wartość).

  2. Dobrze byłoby też uwzględnić wielkość liter w nazwach plików (w Windows nie ma ich rozróżniania, w Linuksie jest) i uwzględnić to (użyć funkcji stristr() lub w regexp modyfikatora "i" w przypadku nie rozróżniania wielkości liter).


(Drobok) #7

A ta funkcja nie zwraca przypadkiem folderów posortowanych ? DIRECT11 DIRECT1122, DIRECT112233 ? Takie jest moje założenie, może jest błędne :slight_smile: Od biedy można posortować tablicę :slight_smile:


(Pablo_Wawa) #8

Wątpię, kiedyś zwracała wpisy w kolejności ich zakładania. Poza tym specyfikacja mówi o tym wyraźnie: http://php.net/manual/en/function.readdir.php

-- Dodane 29.11.2012 (Cz) 19:55 --

Poza tym sortowanie nic nie da - przykład:

foldery DIRECT11 DIRECT112299999, DIRECT112233

plik DIRECT1122334455.txt


(Drobok) #9

No ale DIRECT112233 jest w tym wypadku ostatni (po sortowaniu oczywiście).

co do readdir, rzeczywiście sprawdziłem. Zwraca po swojemu (data utworzenia, ani nazwa to nie są ;/ Bowiem pomiędzy nimi mam pliki z mojego serwera utworzone wcześniej :slight_smile:


(Pablo_Wawa) #10

No co Ty! przecież 3 jest przed 9. Nazwy w kolejności leksykograficznej:

DIRECT11

DIRECT112233

DIRECT112299999

(Drobok) #11

Ech, rzeczywiście sry :))

-- Dodane 29.11.2012 (Cz) 20:26 --

To może takie coś:

s($c){

  $t=$tablica_katalogow;

  for($z=0,$z
    foreach($t as $j){

      if(substr($j, $z, 1)!=substr($c, $z, 1))

        unset($t[$z]);

    }

    if(count($t)=0) break;

  }

}

Może trochę mułowate, wywala elementy sprawdzając kolejne litery, na końcu mamy 1 folder z najdłuższym dopasowaniem.