使用PHP通过FTP递归扫描目录和子目录

发布于 2024-09-30 16:40:27 字数 1080 浏览 3 评论 0原文

我正在尝试创建目录中所有文件(及其大小)的列表,包括子目录中的所有内容。

这些文件位于远程服务器上。因此,我的脚本通过 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 的错误。唯一改变的是我们向服务器添加了更多文件。如果我在子目录上运行该脚本,它就会起作用。但如果我在“.”上运行它它失败了。那么这是因为文件和子目录太多而失败吗?

I'm trying create a list of all files (and their sizes) in a directory including everything within the sub-directories.

The files are on a remote server. So my script connects through FTP, then runs a recursive function using ftp_chdir to go through each directory.

If there's another way to do this, I'm open to suggestions.

$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, ".");

The script worked fine up to a point, but now it's not working. The PHP returns an error with ftp_chdir. The only thing that changed is that we've added more files to the server. The script works if I run it on a sub-directory. But if I run it on "." it fails. So is this failing because there are too many files and sub-directories?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

黒涩兲箜 2024-10-07 16:40:27

我还没有测试过这一点,但这是我不久前的做法:

    $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;
    }

I haven't tested this out, but here's how I did it a while back:

    $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;
    }
德意的啸 2024-10-07 16:40:27

不使用全局变量的真正递归解决方案:

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')
        {
            $dir_files = ftp_list_files_recursive($ftp_stream, $filepath);
            $result = array_merge($result, $dir_files);
        }
        else
        {
            $result[] = $filepath;
        }
    }
    return $result;
}

适用于使用常见 *nix 样式列表的 FTP 服务器,例如:

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

不适用于名称中带有空格的文件。

A real recursive solution that does not use global variables:

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')
        {
            $dir_files = ftp_list_files_recursive($ftp_stream, $filepath);
            $result = array_merge($result, $dir_files);
        }
        else
        {
            $result[] = $filepath;
        }
    }
    return $result;
}

Works for FTP servers that use a common *nix-style listing like:

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

Won't work for files with a space in its name.

朱染 2024-10-07 16:40:27

在我看来,在你给它更多输入之前它就可以工作,这一事实似乎表明这可能是一个问题。尝试在顶部放置一个 set_time_limit(300); ,这将允许它在超时之前运行 5 分钟,看看是否可以解决问题。

The fact that it was working before you gave it more inputs seems to me to suggest that it might be a problem there. Try putting a set_time_limit(300); at the top which will allow it to run for 5 minutes before timing out and see if that fixes the problem.

各自安好 2024-10-07 16:40:27

在 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;
}

Usage of globals in PHP is not good practice. See this:

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文