PHP Conference Japan 2024

ftp_rawlist

(PHP 4, PHP 5, PHP 7, PHP 8)

ftp_rawlist返回给定目录中文件的详细列表

描述

ftp_rawlist(FTP\Connection $ftp, string $directory, bool $recursive = false): array|false

ftp_rawlist() 执行 FTP LIST 命令,并将结果作为数组返回。

参数

ftp

一个 FTP\Connection 实例。

directory

目录路径。可以包含 LIST 命令的参数。

recursive

如果设置为 true,则发出的命令将为 LIST -R

返回值

返回一个数组,其中每个元素对应一行文本。当传递的 directory 无效时返回 false

输出不会以任何方式解析。由 ftp_systype() 返回的系统类型标识符可用于确定如何解释结果。

变更日志

版本 描述
8.1.0 ftp 参数现在期望一个 FTP\Connection 实例;之前,期望一个 resource

示例

示例 #1 ftp_rawlist() 示例

<?php

// 设置基本连接
$ftp = ftp_connect($ftp_server);

// 使用用户名和密码登录
$login_result = ftp_login($ftp, $ftp_user_name, $ftp_user_pass);

// 获取 / 的文件列表
$buff = ftp_rawlist($ftp, '/');

// 关闭连接
ftp_close($ftp);

// 输出缓冲区
var_dump($buff);
?>

以上示例将输出类似以下内容

array(3) {
  [0]=>
  string(65) "drwxr-x---   3 vincent  vincent      4096 Jul 12 12:16 public_ftp"
  [1]=>
  string(66) "drwxr-x---  15 vincent  vincent      4096 Nov  3 21:31 public_html"
  [2]=>
  string(73) "lrwxrwxrwx   1 vincent  vincent        11 Jul 12 12:16 www -> public_html"
}

参见

添加注释

用户贡献的注释 24 个注释

41
fredvanetten at tinqle dot com
11 年前
这是一个简单的函数,它将 ftp_rawlist() 返回的数据解析成一个关联数组。我编写它是因为下面列出的一些函数太长、太复杂或无法处理包含空格的文件名。

<?php
function listDetailed($resource, $directory = '.') {
if (
is_array($children = @ftp_rawlist($resource, $directory))) {
$items = array();

foreach (
$children as $child) {
$chunks = preg_split("/\s+/", $child);
list(
$item['rights'], $item['number'], $item['user'], $item['group'], $item['size'], $item['month'], $item['day'], $item['time']) = $chunks;
$item['type'] = $chunks[0]{0} === 'd' ? 'directory' : 'file';
array_splice($chunks, 0, 8);
$items[implode(" ", $chunks)] = $item;
}

return
$items;
}

// 抛出异常或返回 false < 由您决定
}
?>
4
weltvolk
16 年前
使用此基于此处提供的函数的便捷函数,您可以按字母顺序获取文件列表,所有目录都在顶部

<?php
function rawlist_dump() {
global
$ftp_connect;
$ftp_rawlist = ftp_rawlist($ftp_connect, ".");
foreach (
$ftp_rawlist as $v) {
$info = array();
$vinfo = preg_split("/[\s]+/", $v, 9);
if (
$vinfo[0] !== "total") {
$info['chmod'] = $vinfo[0];
$info['num'] = $vinfo[1];
$info['owner'] = $vinfo[2];
$info['group'] = $vinfo[3];
$info['size'] = $vinfo[4];
$info['month'] = $vinfo[5];
$info['day'] = $vinfo[6];
$info['time'] = $vinfo[7];
$info['name'] = $vinfo[8];
$rawlist[$info['name']] = $info;
}
}
$dir = array();
$file = array();
foreach (
$rawlist as $k => $v) {
if (
$v['chmod']{0} == "d") {
$dir[$k] = $v;
} elseif (
$v['chmod']{0} == "-") {
$file[$k] = $v;
}
}
foreach (
$dir as $dirname => $dirinfo) {
echo
"[ $dirname ] " . $dirinfo['chmod'] . " | " . $dirinfo['owner'] . " | " . $dirinfo['group'] . " | " . $dirinfo['month'] . " " . $dirinfo['day'] . " " . $dirinfo['time'] . "<br>";
}
foreach (
$file as $filename => $fileinfo) {
echo
"$filename " . $fileinfo['chmod'] . " | " . $fileinfo['owner'] . " | " . $fileinfo['group'] . " | " . $fileinfo['size'] . " Byte | " . $fileinfo['month'] . " " . $fileinfo['day'] . " " . $fileinfo['time'] . "<br>";
}
}
rawlist_dump();
?>
7
[email protected]
10年前
这里所有 parse_rawlist 函数都存在一个问题。

当文件以空格字符开头,例如 " robots.txt ",它将被忽略。

重命名、删除将会失败...
2
[email protected]
14年前
获取所有文件(包括隐藏文件,除了 '.' 或 '..')的列表,使用

<?php
ftp_chdir
($connid, $dir);
ftp_rawlist($connid, "-A");
?>

这让我绕圈子好一阵子了!
2
Johnny Doe
14年前
如果有人想通过被动连接使用 MLSD 命令获取详细列表,以下函数可能对您自己的实现有所帮助。

<?php
function ftp_mlsd($ftp, $directory) {
$ok = @ftp_chdir($ftp, $directory);
if (!
$ok) {
return
false;
}
$ret = ftp_raw($ftp, 'PASV');
if (
preg_match(
'/^227.*\(([0-9]+,[0-9]+,[0-9]+,[0-9]+),([0-9]+),([0-9]+)\)$/',
$ret[0], $matches)) {
$controlIP = str_replace(',', '.', $matches[1]);
$controlPort = intval($matches[2])*256+intval($matches[3]);
$socket = fsockopen($controlIP, $controlPort);
ftp_raw($ftp, 'MLSD');
$s = '';
while (!
feof($socket)) {
$s .= fread($socket, 4096);
}
fclose($socket);
$files = array();
foreach (
explode("\n", $s) as $line) {
if (!
$line) {
continue;
}
$file = array();
foreach (
explode(';', $line) as $property) {
list(
$key, $value) = explode('=', $property);
if (
$value) {
$file[$key] = $value;
} else {
$filename = trim($key);
}
}
$files[$filename] = $file;
}
return
$files;
}
return
false;
}
?>

请注意,此函数忽略了 ftp_pasv() 的设置。使该函数对主动和被动连接都普遍适用留作读者练习 ;-)
0
[email protected]
6年前
请注意,如果提供的目录内容为空,此函数也会返回 false。
2
paul [email protected]
16 年前
关于将权限从符号表示法转换为八进制,请注意 [email protected] 的 chmodnum 函数会产生不正确的结果。结果是十进制数,看起来像是八进制数。该函数还忽略了 setuid、setgid 和粘滞位,如果遇到此类文件,将产生不正确的数字。相反,这段蛮力代码有效。也许有更巧妙的方法,但这并不太占用 CPU(请注意,它假设您已经检查过确实有一个 10 个字符的字符串!)。

$permissions = 'drwxr-xr-x'; // 或其他
$mode = 0;

if ($permissions[1] == 'r') $mode += 0400;
if ($permissions[2] == 'w') $mode += 0200;
if ($permissions[3] == 'x') $mode += 0100;
else if ($permissions[3] == 's') $mode += 04100;
else if ($permissions[3] == 'S') $mode += 04000;

if ($permissions[4] == 'r') $mode += 040;
if ($permissions[5] == 'w') $mode += 020;
if ($permissions[6] == 'x') $mode += 010;
else if ($permissions[6] == 's') $mode += 02010;
else if ($permissions[6] == 'S') $mode += 02000;

如果 ($permissions[7] == 'r') $mode += 04;
如果 ($permissions[8] == 'w') $mode += 02;
如果 ($permissions[9] == 'x') $mode += 01;
否则如果 ($permissions[9] == 't') $mode += 01001;
否则如果 ($permissions[9] == 'T') $mode += 01000;

printf('模式为 %d 十进制和 %o 八进制', $mode, $mode);
2
admin at mikeholloway dot co dot uk
19 年前
我在使用 cjacobsen at pge dot cl 的 (11-Jan-05) 解决方案在 Mac 上获取目录时遇到问题。对正则表达式的轻微修改对我有用

ereg("([-dl][rwxstST-]+).* ?([0-9 ]* )?([a-zA-Z0-9]+).* ([a-zA-Z0-9]+).* ([0-9]*) ([a-zA-Z]+[0-9: ]*[0-9])[ ]+(([0-9]{2}:[0-9]{2})|[0-9]{4}) (.+)", $file, $regs)
0
John
14年前
这里给出了几个与 PHP 相关的导致 ftp_rawlist 返回空结果的原因。但是请注意,ZoneAlarm(以及可能的其他)防火墙可能会阻止响应,而没有任何明显的提示,因此请务必首先检查这一点。
0
nospam at advancedonsite dot com
15 年前
ftp_rawlist 一直返回空的文件夹列表,它在某些机器上可以工作,但在其他机器上却不行,事实证明需要 ftp_pasv 命令。
非常令人沮丧
1
marc dot peterlongo at francetelecom dot com
19 年前
当你尝试

$path = "包含空格的目录路径名";
$list = ftp_rawlist($conn_id,$path);

它不起作用

但是当你尝试

$path = "包含空格的目录路径名";
ftp_chdir($conn_id,$path);
$list = ftp_rawlist($conn_id,".");

它起作用
0
ahmadmarafa at gmail dot com
15 年前
这是一个检查目录的函数

<?php
function ftp_isdir($connect_id,$dir)
{
if(
ftp_chdir($connect_id,$dir))
{
ftp_cdup($connect_id);
return
true;

}
else
{
return
false;
}
}
?>
0
tmp at gmx dot de
15 年前
为了格式化此函数的_递归_结果,我使用以下代码

<?php
$conn_id
= ftp_connect(FTP_SERVER);

$login_result = ftp_login($conn_id, FTP_USR, FTP_PASS);

$rawfiles = ftp_rawlist($conn_id, '/', true);

ftp_close($conn_id);

// 这里开始魔法!
$structure = array();
$arraypointer = &$structure;
foreach (
$rawfiles as $rawfile) {
if (
$rawfile[0] == '/') {
$paths = array_slice(explode('/', str_replace(':', '', $rawfile)), 1);
$arraypointer = &$structure;
foreach (
$paths as $path) {
foreach (
$arraypointer as $i => $file) {
if (
$file['text'] == $path) {
$arraypointer = &$arraypointer[ $i ]['children'];
break;
}
}
}
} elseif(!empty(
$rawfile)) {
$info = preg_split("/[\s]+/", $rawfile, 9);
$arraypointer[] = array(
'text' => $info[8],
'isDir' => $info[0]{0} == 'd',
'size' => byteconvert($info[4]),
'chmod' => chmodnum($info[0]),
'date' => strtotime($info[6] . ' ' . $info[5] . ' ' . $info[7]),
'raw' => $info
// 'children' 属性会在文件夹至少包含一个文件时自动添加
);
}
}

// $structure 中包含所有数据
print_r($structure);

// 一些辅助函数
function byteconvert($bytes) {
$symbol = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
$exp = floor( log($bytes) / log(1024) );
return
sprintf( '%.2f ' . $symbol[ $exp ], ($bytes / pow(1024, floor($exp))) );
}

function
chmodnum($chmod) {
$trans = array('-' => '0', 'r' => '4', 'w' => '2', 'x' => '1');
$chmod = substr(strtr($chmod, $trans), 1);
$array = str_split($chmod, 3);
return
array_sum(str_split($array[0])) . array_sum(str_split($array[1])) . array_sum(str_split($array[2]));
}

?>
1
匿名用户
20 年前
请注意,格式没有标准,因此当解析例程在某些服务器上完美运行,而在某些服务器上却惨遭失败时,请不要感到惊讶。
0
francois frao_o
15 年前
为什么不在这里使用 POSIX 正则表达式来完成这项工作呢?preg_replace 将信息返回到一个关联数组中,该数组具有以下键

<权限>
<编号>
<所有者>
<组>
<文件大小>
<修改时间>
<文件>
<类型> * 这是一个额外的好处:它会告诉你项目是文件还是目录

代码如下所示

$list=@ftp_rawlist($con,$directory) ;

$items=array() ;

foreach($list as $_)
preg_replace(

'`^(.{10}+)(\s*)(\d{1})(\s*)(\d*|\w*)'.
'(\s*)(\d*|\w*)(\s*)(\d*)\s'.
'([a-zA-Z]{3}+)(\s*)([0-9]{1,2}+)'.
'(\s*)([0-9]{2}+):([0-9]{2}+)(\s*)(.*)$`Ue',

'$items[]=array(
"rights"=>"$1",
"number"=>"$3",
"owner"=>"$5", "group"=>"$7",
"file_size"=>"$9",
"mod_time"=>"$10 $12 $14:$15",
"file"=>"$17",
"type"=>print_r((preg_match("/^d/","$1"))?"dir":"file",1));',

$_) ; # :p
0
www.bosssftp.com
16 年前
某些 FTP 服务器仅允许您获取当前工作目录下文件的列表。因此,如果您始终获取结果为空数组(array(0){ }),请尝试在获取列表之前更改 cwd



<?php
function ftprawlist($connid, $dir) {
ftp_chdir($connid, $dir);
return
ftp_rawlist($connid, "-a");
}
?>
0
[email protected]
18年前
这更简洁一些

function parse_rawlist( $array )
{
foreach($array as $curraw)
{
$struc = array();
$current = preg_split("/[\s]+/",$curraw,9);

$struc['perms'] = $current[0];
$struc['number'] = $current[1];
$struc['owner'] = $current[2];
$struc['group'] = $current[3];
$struc['size'] = $current[4];
$struc['month'] = $current[5];
$struc['day'] = $current[6];
$struc['time'] = $current[7];
$struc['year'] = $current[8];
$struc['raw'] = $curraw;
$structure[$struc['name']] = $struc;
}
return $structure;

}
-2
[email protected]
10年前
[email protected] 的解决方案很好,但需要进一步评估,因为由于 preg_split 和变量的静态列表将产生不同的值:比较今天或更早的文件,来自前一年

数组
(
[time] => 2012
[day] => 11
[month] => Sep
[size] => 37262
[group] => group
[user] => owner
[number] => 1
[rights] => -rw-rw-rw-
)

数组
(
[time] => 14:01
[day] => 23
[month] => Apr
[size] => 37262
[group] => group
[user] => owner
[number] => 1
[rights] => -rw-rw-rw-
)
0
[email protected]
19 年前
此代码片段修复了列表中的日期问题并整理了变量

$filedata['access_permissions']
$filedata['link_count']
$filedata['uid']
$filedata['gid']
$filedata['size']
$filedata['mod_date_month']
$filedata['mod_date_day']
$filedata['mod_time']
$filedata['name']

list($filedata['access_permissions'], $filedata['link_count'], $filedata['uid'], $filedata['gid'], $filedata['size'], $filedata['mod_date_month'], $filedata['mod_date_day'], $filedata['mod_time'], $filedata['name']) = preg_split("/[\s,]+/", $value);

$filedata['type'] = $filedata['access_permissions']{0};

$filedata['access_permissions'] = substr($filedata['access_permissions'],1);

// 现在检查日期以查看上次修改是在今年还是去年。

if ( strrpos($filedata['mod_time'], ':') != 2 ) { $filedata['mod_date'] = $filedata['mod_date_month'] ." " . $filedata['mod_date_day'] . " " . $filedata['mod_time']; $filedata['mod_time'] = "00:00"; } else { $filedata['mod_date'] = $filedata['mod_date_month'] ." " . $filedata['mod_date_day'] . " " . date("Y"); }
0
[email protected]
19 年前
优秀的表达式,但在 'x' 被禁用时不匹配 SUID、SGUI 和 Sticky 标志。使用 [rwxstST-] 修复它。

<?php

function itemize_dir($contents) {
foreach (
$contents as $file) {
if(
ereg("([-dl][rwxstST-]+).* ([0-9]*) ([a-zA-Z0-9]+).* ([a-zA-Z0-9]+).* ([0-9]*) ([a-zA-Z]+[0-9: ]*[0-9])[ ]+(([0-9]{2}:[0-9]{2})|[0-9]{4}) (.+)", $file, $regs)) {
$type = (int) strpos("-dl", $regs[1]{0});
$tmp_array['line'] = $regs[0];
$tmp_array['type'] = $type;
$tmp_array['rights'] = $regs[1];
$tmp_array['number'] = $regs[2];
$tmp_array['user'] = $regs[3];
$tmp_array['group'] = $regs[4];
$tmp_array['size'] = $regs[5];
$tmp_array['date'] = date("m-d",strtotime($regs[6]));
$tmp_array['time'] = $regs[7];
$tmp_array['name'] = $regs[9];
}
$dir_list[] = $tmp_array;
}
return
$dir_list;
}
$buff = ftp_rawlist($cid, "/");
$items = itemize_dir($buff);

?>
0
[email protected]
19 年前
列出所有(包括隐藏文件和目录)
<?php
$contents
= ftp_rawlist($conn_id, "-al ".$dir_name);
?>

就像 ftp 命令一样
LIST al

"-aF " 等于 '-al',请参考 "ls --help"
0
[email protected]
20 年前
之前的正则表达式(由 Jonathan Almarez、[email protected][email protected])非常好。但我发现它没有考虑到目录(数字 > 9)

将 [0-9] 更改为 [0-9]*

下面的代码不仅解析
drwxrwxr-x 9 msik ia 4096 Nov 5 14:19 Group3

它还解析
drwxrwxr-x 19 msik ia 4096 Nov 5 14:19 Group3
3
drwxrwxr-x 119 msik ia 4096 Nov 5 14:19 Group3
3

0 = 文件
1 = 目录
2 = 符号链接
<?php

function itemize_dir($contents) {
foreach (
$contents as $file) {
if(
ereg("([-dl][rwxst-]+).* ([0-9]*) ([a-zA-Z0-9]+).* ([a-zA-Z0-9]+).* ([0-9]*) ([a-zA-Z]+[0-9: ]*[0-9])[ ]+(([0-9]{2}:[0-9]{2})|[0-9]{4}) (.+)", $file, $regs)) {
$type = (int) strpos("-dl", $regs[1]{0});
$tmp_array['line'] = $regs[0];
$tmp_array['type'] = $type;
$tmp_array['rights'] = $regs[1];
$tmp_array['number'] = $regs[2];
$tmp_array['user'] = $regs[3];
$tmp_array['group'] = $regs[4];
$tmp_array['size'] = $regs[5];
$tmp_array['date'] = date("m-d",strtotime($regs[6]));
$tmp_array['time'] = $regs[7];
$tmp_array['name'] = $regs[9];
}
$dir_list[] = $tmp_array;
}
return
$dir_list;
}
$buff = ftp_rawlist($cid, "/");
$items = itemize_dir($buff);

?>

0
匿名
20 年前
如果你写
<?php
rawlist
($ftp, "-a");
?>
该命令将为 "LIST -a",因此返回的列表也将包含隐藏文件,例如 ".htaccess"。

在这种情况下,包含当前目录的所有文件和文件夹。
要列出另一个文件夹,必须使用 "ftp_chdir" 更改到该文件夹。
-1
eros at speedy dot com dot ar
20 年前
不,不,不。

以上示例均错误,数组中给出的空格并非“仅仅因为”,它只是一个制表符结构。在 PHP 中,我们没有像 C/C++ 中那样的结构,但以下函数可以完成此任务。

<?php

function parse_rawlist( $array ) {

for (
$i = 1; $i < count($array); $i++ ) {

$current = $array[$i];

$structure[$i]['perms'] = substr($current, 0, 10);
$structure[$i]['number'] = trim(substr($current, 11, 3));
$structure[$i]['owner'] = trim(substr($current, 15, 8));
$structure[$i]['group'] = trim(substr($current, 24, 8));
$structure[$i]['size'] = trim(substr($current, 33, 8));
$structure[$i]['month'] = trim(substr($current, 42, 3));
$structure[$i]['day'] = trim(substr($current, 46, 2));
$structure[$i]['time'] = substr($current, 49, 5);
$structure[$i]['name'] = substr($current, 55, strlen($current) - 55);

}

return
$structure;

}

?>
To Top