Рекурсивно сканиране на директория и поддиректории през FTP с PHP

Опитвам се да създам списък с всички файлове (и техните размери) в директория, включително всичко в поддиректориите.

Файловете са на отдалечен сървър. Така че моят скрипт се свързва през FTP, след което изпълнява рекурсивна функция, използвайки ftp_chdir, за да премине през всяка директория.

Ако има друг начин да направите това, отворен съм за предложения.

$flist = array();

function recursive_list_dir($conn_id, $dir, $parent = "false") {
 global $flist;
 ftp_chdir($conn_id, $dir) or die("Fudgeballs: ".$parent."/".$dir);
 $list = array();
 $list = ftp_rawlist($conn_id, ".");

 if($parent != "false") { $dir = $parent."/".$dir; }

 for($x = 0; $x < count($list); $x++) {
  $list_details = preg_split("/[\s]+/", $list[$x]);
  $file = $list_details[3];
  $size = $list_details[2];

  if(!strstr($file, ".")) { // if there's no dot (.), then we assume it's a directory (is there a command similar to "is_dir" for FTP? that would be more fail proof?)
   recursive_list_dir($conn_id, $file, $dir);
  }
  else { $flist[] = $dir."@".$file."@".$size; }
 }
 ftp_chdir($conn_id, "..");
}

recursive_list_dir($conn_id, ".");

Скриптът работеше добре до определен момент, но сега не работи. PHP връща грешка с ftp_chdir. Единственото нещо, което се промени е, че добавихме още файлове към сървъра. Скриптът работи, ако го стартирам в поддиректория. Но ако го пусна на "." не успява. Така че това не успява ли, защото има твърде много файлове и поддиректории?


person Julian    schedule 05.11.2010    source източник
comment
Предполагам, че не можете да стартирате нищо на отдалечения сървър? (също без php скриптове или така)   -  person thejh    schedule 06.11.2010


Отговори (4)


Не съм тествал това, но ето как го направих преди време:

    $hostname = 'write.your.server.here';
    $username = 'username';
    $password = 'password';
    $startdir = 'starting/directory'; // absolute path
    $suffix   = "gif,png,jpeg,pdf,php"; // suffixes to list
    $files = array();
    $conn_id = ftp_connect($hostname);
    $login = ftp_login($conn_id, $username, $password);
    if (!$conn_id) {
        echo 'Wrong server!';
        exit;
    } else if (!$login) {
        echo 'Wrong username/password!';
        exit;
    } else {

        $files = raw_list("$startdir");
    }

    ftp_close($conn_id);

    function raw_list($folder) {
        global $conn_id;
        global $suffix;
        global $files;
        $suffixes = explode(",", $suffix);
        $list     = ftp_rawlist($conn_id, $folder);
        $anzlist  = count($list);
        $i = 0;
        while ($i < $anzlist) {
            $split    = preg_split("/[\s]+/", $list[$i], 9, PREG_SPLIT_NO_EMPTY);
            $itemname = $split[8];
            $endung   = strtolower(substr(strrchr($itemname ,"."),1));
            $path     = "$folder/$itemname";
            if (substr($list[$i],0,1) === "d" AND substr($itemname,0,1) != ".") {
                raw_list($path);
            } else if(substr($itemname,0,2) != "._" AND in_array($endung,$suffixes)) {
                array_push($files, $path);
            }
            $i++;
        }
        return $files;
    }
person tpae    schedule 05.11.2010

Фактът, че работеше, преди да му дадете повече входове, ми се струва, че предполага, че може да е проблем там. Опитайте да поставите set_time_limit(300); в горната част, което ще му позволи да работи 5 минути, преди да изтече времето за изчакване, и вижте дали това ще реши проблема.

person Reese Moore    schedule 05.11.2010
comment
Ръководството за PHP казва, че времевият лимит по подразбиране е 30 секунди. И max_execution_time на PHP на моя сървър е 120. Когато моят скрипт се изпълняваше в миналото, щеше да отнеме известно време, за да завърши - повече от 120 секунди. Как е възможно? PHP измерва ли време отделни команди или целия скрипт? Опитах да го настроя на 300 секунди и нищо не се промени. - person Julian; 06.11.2010

Реално рекурсивно решение, което не използва глобални променливи:

function ftp_list_files_recursive($ftp_stream, $path)
{
    $lines = ftp_rawlist($ftp_stream, $path);

    $result = array();

    foreach ($lines as $line)
    {
        $tokens = explode(" ", $line);
        $name = $tokens[count($tokens) - 1];
        $type = $tokens[0][0];

        $filepath = $path . "/" . $name;
        if ($type == 'd')
        {
            $result = array_merge($result, ftp_list_files_recursive($ftp_stream, $filepath));
        }
        else
        {
            $result[] = $filepath;
        }
    }
    return $result;
}

Работи за FTP сървъри, които използват общ списък в стил *nix като:

-r--r--r-- 1 ftp ftp             13 Nov 09  2015 file.txt
dr-xr-xr-x 1 ftp ftp              0 Nov 10  2015 folder

Няма да работи за файлове с интервал в името си.

person Martin Prikryl    schedule 30.03.2016

Използването на глобали в PHP не е добра практика. Виж това:

function ftp_get_files_list( $conn_id, $baseDir='.' ) {
    $files = array();
    $dirs = array($baseDir);
    while( $dir = array_shift($dirs) ) {
        $list = ftp_rawlist( $conn_id, $dir);
        while( $line = array_shift($list) ) {
            $col = preg_split( "@\s+@", $line );
            if (count($col) <= 2) continue;
            $fname = implode(' ',array_slice($col,8)); // support filenames with spaces
            $isDir =($col[0][0]=='d');
            if ($isDir)
                array_push($dirs, $dir.'/'.$fname );
            else
                array_push($files, $dir.'/'.$fname );
        }
    }
    return $files;
}
person Pafkone    schedule 02.10.2014