Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: readdir - odczytywanie elementu z folderu
Forum PHP.pl > Forum > PHP
fiasko
Jak odczytać pliki w katalogu według najstarszego zmodyfikowanego elementu wykorzystując do tego dane systemowe. Co polecacie zamiast readdir ?

Mam kamerę , która wrzuca zdjęcia na serwer FTP. Muszę co jakiś czas te zdjęcia wykasować i robię to w CRON.

Zdjęć jest kilka mln i żeby nie zajechać serwera i nie czytać od początku za każdym razem wywołania pętli while chcę czytać pliki od końca daty modyfikacji według daty systemowej.

Jak to zrobić ?

Funkcja readdir czyta według uporządkowania w systemie. A ja mam pliki o takich nazwach i są one troszkę pomieszane.

  1. 001E1A010429(przed_firma)_1_20110509231313_328277.jpg
  2. 001E1A010429(przed_firma)_1_20110509221913_326040.jpg
  3. 001E1A010429(przed_firma)_1_20110509103212_298944.jpg
  4. 001E1A010429(przed_firma)_1_20110511102719_387392.jpg
  5. 001E1A010429(przed_firma)_1_20110512151125_432401.jpg
  6. 001E1A010429(przed_firma)_1_20110509125344_304879.jpg
  7. 001E1A010429(przed_firma)_1_20110509025940_283996.jpg
  8. 001E1A010429(przed_firma)_1_20110510172900_367864.jpg
  9. 001E1A010429(przed_firma)_1_20110509144611_309867.jpg
  10. 001E1A010429(przed_firma)_1_20110509232745_328890.jpg
  11. 001E1A010429(przed_firma)_1_20110510040653_340492.jpg
  12. 001E1A010429(przed_firma)_1_20110510013152_334043.jpg
  13. 001E1A010429(przed_firma)_1_20110509022951_282705.jpg
  14. 001E1A010429(przed_firma)_1_20110510083908_348037.jpg
  15. 001E1A010429(przed_firma)_1_20110512101557_421408.jpg
  16. 001E1A010429(przed_firma)_1_20110510062142_343701.jpg
  17. 001E1A010429(przed_firma)_1_20110510003643_331754.jpg
  18. 001E1A010429(przed_firma)_1_20110510015715_335100.jpg
  19. 001E1A010429(przed_firma)_1_20110511233822_411043.jpg


Byłoby fajnie gdybym mógł odczytać pliki według najstarszego elementu lub np. jeśli data modyfikacji wynosi ileś tam .



Teraz mam to tak odczytywane i kasowane :
  1. <?
  2. $data = strftime('%Y-%m-%d %H:%M:%S', mktime());
  3. $data = strtotime($data);
  4. $data_o = $data - 3600 * 24 * 30 ; // data z ostaniach 30 dni
  5. $data = strftime('%Y-%m-%d %H:%M:%S', $data_o);
  6.  
  7. //echo "test".$data.'<br>';
  8. $katalog_sciezka = "/home/domena/domains/domena/.pl/public_html/kamera_nr15/";
  9. $licz = 0;
  10. if(is_dir($katalog_sciezka)) { // jeśli istnieje katalog
  11. $dir = opendir($katalog_sciezka) ;
  12. while($file_name=readdir($dir))
  13. {
  14. if(($file_name!=".")&&($file_name!=".."))
  15. {
  16. echo $file_name.'<br>';
  17. $p = strrpos($file_name , '_');
  18. $data_file_y = substr($file_name ,28 , 4 );
  19. $data_file_m = substr($file_name ,32 , 2 );
  20. $data_file_d = substr($file_name ,34 , 2 );
  21.  
  22. $data_file = $data_file_y.'-'.$data_file_m.'-'.$data_file_d.' 00:00:00';
  23. $data_file2 = strtotime($data_file);
  24.  
  25. if ($data_o >= $data_file2 ){
  26. unlink($katalog_sciezka.$file_name);
  27. //echo "kasujemy<br>";
  28. }
  29. $data_file2 = strftime('%Y-%m-%d %H:%M:%S',$data_file2);
  30. // echo $data_file.'<br>';
  31. //echo $data_file2.'<br>';
  32. }
  33. $licz++;
  34. if($licz >= 50000) {
  35. closedir($dir);
  36. break;
  37. }
  38.  
  39. }
  40. closedir($dir);
  41. }
  42. ?>
  43.  
  44.  
  45.  



Zyx
Funkcje systemowe nie zwracają katalogów w żadnym ściśle i jednolicie określonym porządku. Zadanie posortowania tego tak, jak chcemy, należy do konkretnego programu. W Twoim przypadku musisz zassać funkcją stat() informacje o czasie modyfikacji, wpakować wszystko do tablicy i zamieszać jakimś usort().
fiasko
Problem w tym, że ja nie chcę czytać każdego pliku z dysku bo wykonanie pętli przekracza dopuszczalny czas serwera. Czytanie wszystkich plików jest bez sensu bo nie zdołam ich przetworzyć podczas jednego przebiegu.

Gdybym mógł wznowić czytanie od jakiegoś innego elementu na którym skończyłem poprzednio czytać to też by mnie to urządzało . A tu za każdym razem muszę czytać od nowa.
Zyx
Oczywiście, poruszyła mnie Twoja historia, ale: funkcje systemowe nie zwracają katalogów w żadnym ściśle i jednolicie określonym porządku. Zadanie posortowania tego tak, jak chcemy, należy do konkretnego programu.

Zawsze możesz sobie inaczej rozplanować strukturę katalogów.
ixpack
Jestem "noobem", darko niedawno podsunął mi Iterator... Może Ci się przydać DirectoryIterator, masz tam takie metody jak np. getMTime(), lub seek() - mogą być pomocne.

Nie używałem (jeszcze) tego, ale w teorii: skrypt robi co ma robić, zapisuje pozycję ostatniego pliku i seek'iem powracasz do tej pozycji.
fiasko
Cytat
Zawsze możesz sobie inaczej rozplanować strukturę katalogów.


Tak tylko kamera wrzuca fotki do jednego katalogu. Nie mam też wpływu na nazwy plików .
Mogę odczytywać jedynie ich atrybuty lub parsować nazwę i po tym odczytywać jaka była data zapisu. Jednak tak jak pisałem ogranicza mnie czas wykonywania pętli.
Fifi209
scandir + implode + preg_match
scandir - odczytasz listę plików
implode - złączysz tablicę otrzymaną wyżej
preg_match - wyciągniesz daty
melkorm
albo jeżeli masz dostęp do komendy system to
Kod
ls -t /path/


Czyli lista plików posortowana po czasie modyfikacji ( malejąco ).

I sobie obrób output.
Zyx
A wszystkie te sposoby to zwykłe opakowanie na to, co napisałem: pobieranie listy plików, zrobienie stat() na każdym z nich i posortowanie.

Co do kamerki, to co Ci szkodzi napisać inny skrypt (albo nawet dorobić funkcję do tego samego), która wczytuje zawartość katalogu z obrazkami z kamerki, kopiuje ją gdzieś indziej w jakiś rozsądniejszy sposób i czyści oryginalny katalog, rozpoczynając czekanie na kolejną porcję danych?
Fifi209
Cytat(Zyx @ 13.05.2011, 20:33:16 ) *
A wszystkie te sposoby to zwykłe opakowanie na to, co napisałem: pobieranie listy plików, zrobienie stat() na każdym z nich i posortowanie.

Nie, bo Ty chcesz odczytywać z każdego pliku, a w moim rozwiązaniu wystarczy pobrać listę plików, a z ich nazwy potem preg_match'em jednym wyciągnąć i posortować IMHO tak będzie szybciej, nie sądzisz?
Crozin
@fifi209: Tak, bo wyrażenia regularne to przecież operacja atomowa, która wykonuje się w zerowym czasie.

Nie masz tutaj za dużego wyboru. Jak już zauważył @Zyx kolejność w jakiej pliki zostaną odczytane można wręcz traktować jako losową - jest to tak niestabilna rzecz, że poleganie na niej byłoby skończonym idiotyzmem. Musisz po prostu odczytywać nazwy tych plików i wydobyć z nich czas ich ostatniej modyfikacji czy to poprzez odpytanie systemu plików o tą informację czy wyciągając ją z samej nazwy pliku - nie wiem co będzie szybsze. Jeżeli masz problemy z wydajnością poszukaj co najbardziej obciąża skrypt i spróbuj to jakoś odchudzić - jak nie będziesz potrafił na pewno postaramy się pomóc. Ostatecznie licz się z tym, że przetwarzanie danych czasami zajmuje trochę czasu i być może trzeba będzie zwiększyć limity bądź zmienić maszynę.
Możesz też spróbować np. w C - sam język i sposób jego działania da Ci zaoszczędzić trochę zasobów - napisać program, który będzie zajmować się jakimś sensownym rozmieszczeniem tych plików tak by PHP mógł spokojnie na nich operować.

@fifi209: Tak, bo wyrażenia regularne to przecież operacja atomowa, która wykonuje się w zerowym czasie.

Nie masz tutaj za dużego wyboru. Jak już zauważył @Zyx kolejność w jakiej pliki zostaną odczytane można wręcz traktować jako losową - jest to tak niestabilna rzecz, że poleganie na niej byłoby skończonym idiotyzmem. Musisz po prostu odczytywać nazwy tych plików i wydobyć z nich czas ich ostatniej modyfikacji czy to poprzez odpytanie systemu plików o tą informację czy wyciągając ją z samej nazwy pliku - nie wiem co będzie szybsze. Jeżeli masz problemy z wydajnością poszukaj co najbardziej obciąża skrypt i spróbuj to jakoś odchudzić - jak nie będziesz potrafił na pewno postaramy się pomóc. Ostatecznie licz się z tym, że przetwarzanie danych czasami zajmuje trochę czasu i być może trzeba będzie zwiększyć limity bądź zmienić maszynę.
Możesz też spróbować np. w C - sam język i sposób jego działania da Ci zaoszczędzić trochę zasobów - napisać program, który będzie zajmować się jakimś sensownym rozmieszczeniem tych plików tak by PHP mógł spokojnie na nich operować.
JohnnyB
Właśnie niedawno pisałem podobną funkcję, zobacz, może Ci wystarczy:

  1. function cmp($a,$b) {
  2. return $b['time']-$a['time'];
  3. }
  4.  
  5. function ls($path) {
  6. if(is_dir($path)) {
  7. $d=$path; $b='*';
  8. } else {
  9. $d=dirname($path);
  10. $b=basename($path);
  11. }
  12. $dir=scandir($d); $res=array();
  13. foreach($dir as $entry) {
  14. if($entry=='.' || $entry=='..' || !fnmatch($b,$entry)) continue;
  15. $type=is_dir("$d/$entry")?'d':'f';
  16. $mt=filemtime("$d/$entry");
  17. $res[]=array('name'=>"$d/$entry",'type'=>$type,'time'=>$mt);
  18. }
  19. // posortowanie po dacie modyfikacji
  20. uasort($res,'cmp');.
  21. return $res;
  22. }


To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.