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 實例;先前,期望的是一個 資源

範例

範例 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
mediaboat at gmail dot com
10 年前
這裡所有的 parse_rawlist 函式都有一個問題。

當檔案名稱以空格字元開頭時,例如 " robots.txt ",它將會被忽略。

重新命名、刪除將會失敗...
2
shaun at shaunfreeman dot co dot uk
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
Roline88 at hotmail dot com
6 年前
請注意,如果提供的目錄內容為空,此函式也會回傳 false。
2
paul maybe at squirrel mail org
16 年前
關於將權限從符號表示法轉換為八進位表示法,請注意 Hazem dot Khaled 在 gmail dot com 的 chmodnum 函式會產生**不正確**的結果。結果是看起來像八進位數字的十進位數字。該函式也會忽略 setuid、setgid 和 sticky 位元,如果遇到這類檔案,將會產生不正確的數字。相反地,這個暴力破解程式碼可以運作。也許有更簡潔的方法,但這個方法的 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;

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

printf('Mode is %d decimal and %o octal', $mode, $mode);
2
admin at mikeholloway dot co dot uk
19 年前
我在使用 cjacobsen 在 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
Anonymous
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
ari at bs-inc dot com
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
nickman at freemail dot hu
10 年前
fredvanetten 在 tinqle dot com 的解決方案很好,但需要進一步評估,因為 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
nate at 8networks dot com
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
cjacobsen at pge dot cl
19 年前
很棒的表達式,但當 'x' 被停用時,不會匹配 SUID、SGID 和 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
greg at upsdn dot net
19 年前
列出所有(包括隱藏的檔案和目錄)
<?php
$contents
= ftp_rawlist($conn_id, "-al ".$dir_name);
?>

就像 ftp 命令一樣
LIST al

"-aF " 等於 '-al',請參考 "ls --help"
0
greg at upsdn dot net
20 年前
先前的正規表達式(由 Jonathan Almarez,ergye at yahoo dot com 和 guru at virusas dot lt 提供)非常好。但我發現它沒有考慮到目錄(數字 > 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
Anonymous
20 年前
如果你寫
<?php
rawlist
($ftp, "-a");
?>
命令將會是 "LIST -a",所以返回的清單也會包含像 ".htaccess" 這樣的隱藏檔案。

在這種情況下,會包含目前目錄的所有檔案和資料夾。
要列出另一個資料夾,您必須使用 "ftp_chdir" 切換到它。
-1
eros at speedy dot com dot ar
20 年前
不,不,不。

上面的例子都是錯誤的,陣列中給定的空格不是「僅僅因為」,它只是一個標籤結構。在 php 中,我們沒有像 c/cpp 中的結構,但下面的函數可以完成這項工作。

<?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