opendir

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

opendir打开目录句柄

描述

opendir(string $directory, ?resource $context = null): resource|false

打开一个目录句柄,以便在后续的 closedir()readdir()rewinddir() 调用中使用。

参数

directory

要打开的目录路径

context

有关 context 参数的描述,请参阅手册的 流部分

返回值

如果成功,则返回一个目录句柄 resource,如果失败,则返回 false

错误/异常

如果失败,将发出一个 E_WARNING

这可能发生在 directory 不是有效目录,由于权限限制或文件系统错误而无法打开目录的情况下。

变更日志

版本 描述
8.0.0 context 现在可以为空。

示例

示例 #1 opendir() 示例

<?php
$dir
= "/etc/php5/";

// 打开一个已知目录,并继续读取其内容
if (is_dir($dir)) {
if (
$dh = opendir($dir)) {
while ((
$file = readdir($dh)) !== false) {
echo
"filename: $file : filetype: " . filetype($dir . $file) . "\n";
}
closedir($dh);
}
}
?>

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

filename: . : filetype: dir
filename: .. : filetype: dir
filename: apache : filetype: dir
filename: cgi : filetype: dir
filename: cli : filetype: dir

参见

  • is_dir() - 判断文件名是否为目录
  • readdir() - 从目录句柄中读取条目
  • dir() - 返回 Directory 类的实例

添加注释

用户贡献的注释 33 个注释

hz_php at hotmail dot com { hussam alzahabi }
8 年前
有时程序员需要访问包含阿拉伯语名称的文件夹内容,但 opendir 函数将返回空资源 ID

为此,我们必须使用 iconv 函数将 dirname 字符集从 utf-8 转换为 windows-1256,前提是 preg_match 函数检测到阿拉伯字符,并使用“U”附加性来启用多字节匹配

<?php

$dir
= ("./"); // 在此文件目录中

// 检测路径中是否包含阿拉伯字符,并使用“u”可选项以启用函数匹配多字节字符

if (preg_match('#[\x{0600}-\x{06FF}]#iu', $dir) )
{

// 将输入(utf-8)转换为输出(windows-1256)

$dir = iconv("utf-8","windows-1256",$dir);

}

if(
is_dir($dir) )
{


if( (
$dh = opendir($dir) ) !== null )
{


while ( (
$file = readdir($dh) ) !== false )
{


echo
"filename: ".$file ." filetype : ".filetype($dir.$file)."<br/>";


}

}


}

?>
sergio dot barrios at upr dot edu dot cu
8 年前
迭代函数,用于在目录中搜索文件夹或文件。

<?php

$root
= '../Classes';
$search_parameter = "CachedObjectStorageFactory.php";

// 如果我们调用函数 spider 为 spider($root);
// 将显示所有目录内容,包括子目录

// 如果我们调用函数 spider 为 spider('../Classes', 'Shared');
// 将显示目录的地址

spider($root, $search_parameter);
closedir();

function
spider($dir,$fileName=""){

$handle = opendir($dir);

while(
$file= readdir($handle)){

if(
$file != "." && $file != ".."){

if(
$fileName=="")
echo
$dir."/".$file."<br>";
else
if(
$file == $fileName)
echo
$dir."/".$file."<br>";


if(!
is_file($dir."/".$file))
spider($dir."/".$file,$fileName);

}
}

}

?>
DaveRandom
15 年前
关于 Matt 在 Windows 网络驱动器上的文章的一些说明

由于 system() 命令将执行的 shell 命令的输出直接写入输出缓冲区,如果您希望从 Web 浏览器隐藏映射命令的返回结果(即“命令已成功完成”或错误消息),您需要更改发送到 shell 的命令,以便隐藏该命令的输出。

你可能在想“为什么不直接使用 exec()?”,这是一个合理的问题,但由于某些原因,它并不总是有效 - 我猜这是另一个 NT 用户权限问题。如果你想保证你的应用程序在没有任何主机系统上的干扰的情况下正常运行,请使用 system() 命令。

在 Windows 命令行中,你可以通过将输出 (1) 和错误 (2) 消息发送到“nul”来隐藏命令的输出,使用管道,换句话说,在命令末尾加上“>nul 2>&1”。Matt 的帖子中,用户名和密码顺序需要调换。

这里 (http://networkm.co.uk/static/drive.html) 是我写的一个函数,它可以根据当前映射到 PHP 的驱动器字母以及可访问的驱动器字母来动态选择要使用的驱动器字母。

<?php

// 定义 shell 命令的参数
$location = "\\servername\sharename";
$user = "USERNAME";
$pass = "PASSWORD";
$letter = "Z";

// 映射驱动器
system("net use ".$letter.": \"".$location."\" ".$pass." /user:".$user." /persistent:no>nul 2>&1");

// 打开目录
$dir = opendir($letter.":/an/example/path")

...

?>
Lasse Dalegaard
19 年前
我创建了一个函数来查找指定目录及其所有子目录中的所有文件。当你在大量子目录中搜索大量文件时,这个函数非常有用。该函数返回一个包含所有找到的文件路径的数组。

<?
function getFiles($directory) {
// 尝试打开目录
if($dir = opendir($directory)) {
// 创建一个数组,用于存储所有找到的文件
$tmp = Array();

// 添加文件
while($file = readdir($dir)) {
// 确保文件存在
if($file != "." && $file != ".." && $file[0] != '.') {
// 如果是一个目录,列出其中的所有文件
if(is_dir($directory . "/" . $file)) {
$tmp2 = getFiles($directory . "/" . $file);
if(is_array($tmp2)) {
$tmp = array_merge($tmp, $tmp2);
}
} else {
array_push($tmp, $directory . "/" . $file);
}
}
}

// 完成函数
closedir($dir);
return $tmp;
}
}

// 使用示例
print_r(getFiles('.')); // 这将找到当前目录及其所有子目录中的所有文件
?>
sandy at montana-riverboats dot com
19 年前
<?php
/*
** 这个递归文件列表器每次只读取一页,
** 因此,它在大型系统上运行时不会花费很长时间来加载......每页还附带一个“向上”链接。
*/

$PHP_SELF = $_SERVER['PHP_SELF'];
$DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
# 激活下一行(并停用最后一行)来
# 在 $DOCUMENT_ROOT/~anybody
# 环境中使用此脚本。
#$DOCUMENT_ROOT="/home/sandy/public_html/";

$tdir = $_GET['dir'];
echo
"tdir==$tdir<br>";
$tparent_path = $_GET['parent_path'];
$dbg = $_GET['dbg'];

if(!
strstr($tdir, $DOCUMENT_ROOT))
$tdir = getcwd();
if(!
strstr($tparent_path, $DOCUMENT_ROOT))
$tparent_path = $tdir;

if (!isset (
$tdir))
{
$dir = getcwd ();
}
else
$dir = $tdir;

if (!isset (
$tparent_path))
{
$parent_path = $dir;
}
else
$parent_path = $tparent_path;

echo
"<br>";
if (!isset (
$tdir))
{
$upurl = $PHP_SELF;
}
else
{
if (
$parent_path == $DOCUMENT_ROOT)
$parent_parent_path = $parent_path;
else
$parent_parent_path = dirname ($parent_path);
$upurl = $PHP_SELF."?dir=".$parent_path."&parent_path=".
$parent_parent_path;
}

if(
$dbg==1)
{
echo
"PHP_SELF: $PHP_SELF<br>\n";
echo
"DOCUMENT_ROOT: $DOCUMENT_ROOT<br>\n";
echo
"dir: $dir<br>\n";
echo
"parent_path: $parent_path<br>\n";
echo
"upurl: $upurl<br>\n";
}

echo
"<a href=\"$upurl\"> <h3>Up</h3> </a>\n";
echo
"<h2>$dir</h2>\n";

create_tree ($dir, $parent_path);

function
urlFromPath ($path)
{
global
$PHP_SELF;
global
$DOCUMENT_ROOT;
$prefix = "";
if (
substr ($path, 0, 1) != "/")
$prefix = "/";
$url = $prefix.ereg_replace ($DOCUMENT_ROOT, "", $path);
return
$url;
}

function
create_tree ($dir, $parent_path)
{
if (
$handle = opendir ($dir))
{
$i = 0;
while (
false !== ($file = @readdir ($handle)))
{
if (
$file != "." && $file != "..")
{
$list[$i] = $file;
$i++;
}
}
$dir_length = count ($list);
echo
"<ul>";
for (
$i = 0; $i < $dir_length; $i++)
{
global
$PHP_SELF;
global
$DOCUMENT_ROOT;
$label = $list[$i];
$test = $dir."/".$label;
$alink = $dir."/".ereg_replace(" ","%20",$label);
if (!
strstr ($PHP_SELF, $label))
{
if (
is_dir ($test))
{
$tmp = $PHP_SELF. "?dir=".$alink."&parent_path=".$dir;
$url = ereg_replace(" ", "%20", $tmp);
echo
"$url<br>\n";
echo
"<a href=\"$url\"><b>$label</b>/</a><br>\n";
}
else
{
$link = urlFromPath ($alink);

$label = $list[$i];
echo
"<a href=\"$link\">".$label."</a><br>\n";
}
}
}
echo
"</ul>";
closedir ($handle);
}
}

?>
chrys at mytechjournal dot com
18 年前
我写了一个函数,用于从起始目录递归删除文件。我不得不这样做,因为我的服务器不允许我删除 Apache 写入的文件,因为我没有权限,所以... 我让 Apache 完成了这项工作。

<?php
$dir
= "/path/to/base/dir";

recursive_delete($dir);

function
recursive_delete( $dir )
{
if (
is_dir($dir)) {
if (
$dh = opendir($dir)) {
while ((
$file = readdir($dh)) !== false ) {
if(
$file != "." && $file != ".." )
{
if(
is_dir( $dir . $file ) )
{
echo
"Entering Directory: $dir$file<br/>";
recursive_delete( $dir . $file . "/" );
echo
"Removing Directory: $dir$file<br/><br/>";
rmdir( $dir . $file );
}
else
{
echo
"Deleting file: $dir$file<br/>";
unlink( $dir . $file );
}
}
}
closedir($dh);
}
}
}
?>
archipel dot gb at online dot fr
16 年前
以下是列出目录树中所有文件的相同函数的两个版本。

第一个是递归的(在遍历子目录时调用自身)
<?php
function rec_listFiles( $from = '.')
{
if(!
is_dir($from))
return
false;

$files = array();
if(
$dh = opendir($from))
{
while(
false !== ($file = readdir($dh)))
{
// Skip '.' and '..'
if( $file == '.' || $file == '..')
continue;
$path = $from . '/' . $file;
if(
is_dir($path) )
$files += rec_listFiles($path);
else
$files[] = $path;
}
closedir($dh);
}
return
$files;
}
?>

第二个是迭代的(使用更少的内存)
<?php
function listFiles( $from = '.')
{
if(!
is_dir($from))
return
false;

$files = array();
$dirs = array( $from);
while(
NULL !== ($dir = array_pop( $dirs)))
{
if(
$dh = opendir($dir))
{
while(
false !== ($file = readdir($dh)))
{
if(
$file == '.' || $file == '..')
continue;
$path = $dir . '/' . $file;
if(
is_dir($path))
$dirs[] = $path;
else
$files[] = $path;
}
closedir($dh);
}
}
return
$files;
}
?>
迭代版本应该在大多数情况下速度稍微快一点,但最大的区别在于内存使用情况。

这里还有一个性能分析函数(仅在 php5 中有效)
<?php
function profile( $func, $trydir)
{
$mem1 = memory_get_usage();
echo
'<pre>-----------------------
Test run for '
.$func.'() ...
'
; flush();

$time_start = microtime(true);
$list = $func( $trydir);
$time = microtime(true) - $time_start;

echo
'Finished : '.count($list).' files</pre>';
$mem2 = memory_get_peak_usage();

printf( '<pre>Max memory for '.$func.'() : %0.2f kbytes
Running time for '
.$func.'() : %0.f s</pre>',
(
$mem2-$mem1)/1024.0, $time);
return
$list;
}
?>
Alex Dawn
1 年前
<?php

/**
* 这些函数与生成器配合使用,以隐藏所有混乱的文件句柄(有点像 python 的 with 块)
* 删除回声,它们只是为了演示生成器如何与 foreach 循环一起工作。
*
* @param string $filepath
* @return Generator<string>
*/
function generateFiles(string $filepath): Generator
{
echo
"opening handle" . PHP_EOL;
$handle = opendir($filepath);
// 看起来比需要的复杂,但文档说类型检查很重要
// https://php.net/manual/en/function.readdir.php
try {
while (
false !== ($entry = readdir($handle))) {
yield
$entry;
}
} finally {
closedir($handle);
echo
"closed handle" . PHP_EOL;
}
}

foreach (
generateFiles('.') as $file) {
echo
$file . PHP_EOL;
}
Peter Hkansson
16 年前
您想在浏览器中查看您的目录吗?此脚本可能会有所帮助。

<?php
$sub
= ($_GET['dir']);
$path = 'enter/your/directory/here/';
$path = $path . "$sub";
$dh = opendir($path);
$i=1;
while ((
$file = readdir($dh)) !== false) {
if(
$file != "." && $file != "..") {
if (
substr($file, -4, -3) =="."){
echo
"$i. $file <br />";
}else{
echo
"$i. <a href='?dir=$sub/$file'>$file</a><br />";
}
$i++;
}
}
closedir($dh);
?>
mana at averna dot com
16 年前
我尝试使用 opendir 函数访问网络驱动器。我阅读了大量帖子,都说访问网络驱动器几乎是不可能的,最后我终于找到了答案;要使用 PHP 访问同一台机器或另一台机器上的网络驱动器,需要遵循两个步骤。

但首先,这是我遇到的错误
警告:opendir(\\server\folder1\sub_folder) [function.opendir]:无法打开目录:C:\wamp\www\PMOT\v0.1\REPORT_MENU\index.php 第 17 行没有错误

首先,必须确保文件夹 \\server\folder1\sub_folder 可以被用户访问,例如,使用用户名 USER_TEST 和密码 PASS_TEST 的用户。通过设置该文件夹的属性,可以添加此用户并使用正确的密码(USER_TEST 和 PASS_TEST)。

其次,必须设置 APACHE 服务以考虑此用户。如果没有指定用户,APACHE 将使用匿名用户,这就是问题/错误消息的来源。必须进入控制面板->管理工具->服务。将看到服务列表,必须找到描述中包含 Apache/2.X.X 的 APACHE。(对于 Wampserver,它将被称为 wampapache,等等!)右键单击它,然后弹出属性屏幕。在 LOG ON 选项卡中,有两个选项:本地系统帐户和“此帐户”,它将是指定的帐户。在这里必须指定 USER_TEST 和 PASS_TEST。

按照这些步骤,我的问题完美解决了,但如果文件夹权限或 apache 登录用户被禁用,那么我会收到前面提到的初始错误消息。

无论如何,我希望这能帮助到其他人!

干杯!

马克
MetaNull
16 年前
另一种递归遍历目录及其内容的方法,并对每个文件应用回调函数。

例如:更新文件夹中每个文件的最后修改时间

<?php

clearstatcache
();

$sourcepath = "C:/WINDOWS/TEMP";

// 将 \ 替换为 /,并删除最终的 /(如果有)
$root = ereg_replace( "/$", "", ereg_replace( "[\\]", "/", $sourcepath ));
// 触摸 $root 目录中的所有文件
if( false === m_walk_dir( $root, "m_touch_file", true )) {
echo
"'{$root}' 不是一个有效的目录\n";
}

// 递归遍历目录,并对每个文件应用回调函数
function m_walk_dir( $root, $callback, $recursive = true ) {
$dh = @opendir( $root );
if(
false === $dh ) {
return
false;
}
while(
$file = readdir( $dh )) {
if(
"." == $file || ".." == $file ){
continue;
}
call_user_func( $callback, "{$root}/{$file}" );
if(
false !== $recursive && is_dir( "{$root}/{$file}" )) {
m_walk_dir( "{$root}/{$file}", $callback, $recursive );
}
}
closedir( $dh );
return
true;
}

// 如果路径指示一个文件,则在其上运行 touch() 函数
function m_touch_file( $path ) {
echo
$path . "\n";
if( !
is_dir( $path )) {
touch( $path );
}
}

?>
NerdyDork
17 年前
以下代码片段用于创建文件夹中所有 html 文件的站点地图

<?php
// 读取当前目录中的所有 html 文件
if ($dh = opendir('./')) {
$files = array();
while ((
$file = readdir($dh)) !== false) {
if (
substr($file, strlen($file) - 5) == '.html') {
array_push($files, $file);
}
}
closedir($dh);
}

// 对文件进行排序并显示
sort($files);
echo
"<ul>\n";
foreach (
$files as $file) {
$title = Title($file);
echo
"<li><a href=\"$file\" title=\"$title\">$title</a></li>\n";
}
echo
"</ul>\n";

// 函数用于从文件名获取人类可读的标题
function Title($filename) {
$title = substr($filename, 0, strlen($filename) - 5);
$title = str_replace('-', ' ', $title);
$title = ucwords($title);
return
$title;
}
?>
tim2005
18 年前
您好,

我的一位朋友正在运营一家网络主机公司,我认为我发现了这段脚本的安全漏洞

<?php
function select_files($dir, $label = "", $select_name, $curr_val = "", $char_length = 30) {
$teller = 0;
if (
$handle = opendir($dir)) {
$mydir = ($label != "") ? "<label for=\"".$select_name."\">".$label."</label>\n" : "";
$mydir .= "<select name=\"".$select_name."\">\n";
$curr_val = (isset($_REQUEST[$select_name])) ? $_REQUEST[$select_name] : $curr_val;
$mydir .= ($curr_val == "") ? " <option value=\"\" selected>...\n" : "<option value=\"\">...\n";
while (
false !== ($file = readdir($handle))) {
$files[] = $file;
}
closedir($handle);
sort($files);
foreach (
$files as $val) {
if (
is_file($dir.$val)) { // show only real files (ver. 1.01)
$mydir .= " <option value=\"".$val."\"";
$mydir .= ($val == $curr_val) ? " selected>" : ">";
$mydir .= (strlen($val) > $char_length) ? substr($val, 0, $char_length)."...\n" : $val."\n";
$teller++;
}
}
$mydir .= "</select>";
}
if (
$teller == 0) {
$mydir = "No files!";
} else {
return
$mydir;
}
}

echo
select_files("C:/winnt/", "", "", "", "60");
?>

现在我可以看到他 Windows 目录中的历史文件了。这算泄漏吗? 这个问题可以修复吗? 我也会将此报告为 bug!

Tim2005
tozeiler
18 年前
"opendir" 说
------------------------------------------------------------------

2006 年 1 月 23 日 08:04
我只想要一个目录列表和一个可点击的链接来下载文件

<snip>
------
<?
echo ("<h1>目录概述:</h1>");

function getFiles($path) {

<snip 复杂函数内容>

------------------------------------------------------------------
这是一个更直接的将 $path/files 连接起来的方法

<?php

echo "<h1>目录概述:</h1>";

$dh = opendir($path);
while ((
$file = readdir($dh)) !== false) {
echo
"<a href='$path/$file'>$file</a><br />";
}
closedir($dh);

?>
mstabile75 at gmail dot com
18 年前
在我之前的帖子中,我遇到了 $directorylist 的“全局”定义问题。如果我在同一个页面上多次调用该函数,它将合并文件列表。我查看了 Lasse Dalegaard 的示例,并使用了以下解决方案。

删除全局定义
global $directorylist;

替换
<?
if ((($maxlevel) == "all") or ($maxlevel > $level)) {
filelist($startdir . $file . "/", $searchSubdirs, $directoriesonly, $maxlevel, $level + 1);
}
?>
使用
<?
if ((($maxlevel) == "all") or ($maxlevel > $level)) {
$list2 = filelist($startdir . $file . "/", $searchSubdirs, $directoriesonly, $maxlevel, $level + 1);
if(is_array($list2)) {
$directorylist = array_merge($directorylist, $list2);
}
}
?>
Anonymous
18 年前
此函数按名称(不区分大小写)对文件进行排序。它还对文件大小信息进行一些方便的字符串格式化。

<?
function getFiles($path) {
// 函数接受一个路径,并返回一个按关联数组(包含文件信息)进行数字索引的数组,
// 按文件名(不区分大小写)排序。如果两个文件在不区分大小写的情况下比较时相同,它们将按 readdir() 中呈现的顺序进行排序
// 相对彼此排序
$files = array();
$fileNames = array();
$i = 0;

if (is_dir($path)) {
if ($dh = opendir($path)) {
while (($file = readdir($dh)) !== false) {
if ($file == "." || $file == "..") continue;
$fullpath = $path . "/" . $file;
$fkey = strtolower($file);
while (array_key_exists($fkey,$fileNames)) $fkey .= " ";
$a = stat($fullpath);
$files[$fkey]['size'] = $a['size'];
if ($a['size'] == 0) $files[$fkey]['sizetext'] = "-";
else if ($a['size'] > 1024) $files[$fkey]['sizetext'] = (ceil($a['size']/1024*100)/100) . " K";
else if ($a['size'] > 1024*1024) $files[$fkey]['sizetext'] = (ceil($a['size']/(1024*1024)*100)/100) . " Mb";
else $files[$fkey]['sizetext'] = $a['size'] . " bytes";
$files[$fkey]['name'] = $file;
$files[$fkey]['type'] = filetype($fullpath);
$fileNames[$i++] = $fkey;
}
closedir($dh);
} else die ("无法打开目录: $path");
} else die ("路径不是目录: $path");
sort($fileNames,SORT_STRING);
$sortedFiles = array();
$i = 0;
foreach($fileNames as $f) $sortedFiles[$i++] = $files[$f];

return $sortedFiles;
}

$files = getFiles("C:");
foreach ($files as $file) print "$file[name]<br>\n";
?>
iamnotanerd
19 年前
这是我创建的用于搜索文件的代码片段..递归打开目录并搜索匹配项..

<?php
function search($target, $directory){

if(
is_dir($directory)){
$direc = opendir($directory);
while(
false !== ($file = readdir($direc))){

if(
$file !="." && $file != ".."){

if(
is_file($directory."/".$file)){
if(
preg_match("/$target/i", $file)){
echo
"<a href=\"$directory/$file\">$file</a><br>";
}
}else if(
is_dir($directory."/".$file)){
search($target,$directory."/".$file);

}

}
}
closedir($direc);
}

return ;
}
?>
Matt Grimm
21 年前
我想我可以帮助澄清一下在 Windows 网络(在本例中为 2000)上访问网络共享的一些内容,在 Apache 2.0.44 下运行 PHP 4.3.2。

无论你以何种身份登录 Windows 计算机,你的 Apache 服务都必须以具有共享访问权限的帐户运行。对我来说,最简单(也是最不安全)的方法是将 Apache 服务的用户更改为计算机管理员(在“登录”选项卡的服务属性中执行此操作)。重新启动 Apache 后,我可以通过其分配的驱动器号(“z:\\”)访问映射的驱动器,或通过其 UNC 路径(“\\\\shareDrive\\shareDir”)访问常规共享。
hxss at ya dot ru
6 年前
用于处理目录和文件的真正递归映射函数。
你可以通过你的可调用函数创建、读取(查找)、更新(或移动)或删除文件/目录/树。
你可以使用标志来选择你需要的内容。

<?php
var_dump
(dirmap($dst, function($v) {
pre($v);
return
true;
},
1|2|4|8));

/**
* 对给定目录路径的条目应用回调函数
* 按照接收到的标志进行操作
* @param string $path 工作目录路径
* @param Callable $action 可调用函数,将对路径中的每个条目执行
* @param integer $flags 可以是以下标志:
* 1: 对文件应用可调用函数
* 2: 对目录应用可调用函数
* 4: 对 $path 应用可调用函数
* 8: 递归操作
* @return bool 所有 (bool)$action 调用结果的按位与运算
*/
function dirmap(string $path, Callable $action, int $flags = 15) {
$flF = boolval($flags & 1);
$flD = boolval($flags & 2);
$flP = boolval($flags & 4);
$flR = boolval($flags & 8);
$result = 1;

if (
is_dir($path)) {

$dir = opendir($path);
while (
$entry = readdir($dir))
if (!
in_array($entry, ['.', '..'])) {
$fullEntry = "{$path}/{$entry}";

if (
$flR)
$result &= dirmap($fullEntry, $action, $flags & 11);

if (
$flF && is_file($fullEntry) || $flD && is_dir($fullEntry))
$result &= (bool)call_user_func($action, $fullEntry);
}

if (
$flP)
$result &= (bool)call_user_func($action, $fullEntry);

return (bool)
$result;
} else
return
is_file($path);
}
?>
frogstarr78 at yahoo dot com
17 年前
这是一个函数,它将递归地将目录转换为目录哈希和文件数组的哈希,自动忽略“点”文件。

<?php
function hashify_directory($topdir, &$list, $ignoredDirectories=array()) {
if (
is_dir($topdir)) {
if (
$dh = opendir($topdir)) {
while ((
$file = readdir($dh)) !== false) {
if (!(
array_search($file,$ignoredDirectories) > -1) && preg_match('/^\./', $file) == 0) {
if (
is_dir("$topdir$file")) {
if(!isset(
$list[$file])) {
$list[$file] = array();
}
ksort($list);
hashify_directory("$topdir$file/", $list[$file]);
} else {
array_push($list, $file);
}
}
}
closedir($dh);
}
}
}
?>

例如。
<?php
$public_html
["StudentFiles"] = array();
hashify_directory("StudentFiles/", $public_html["StudentFiles"]);
?>
在以下目录结构上
./StudentFiles/tutorial_01/case1/file1.html
./StudentFiles/tutorial_01/case1/file2.html
./StudentFiles/tutorial_02/case1/file1.html
./StudentFiles/tutorial_02/case2/file2.html
./StudentFiles/tutorial_03/case1/file2.html
等等…
变成
<?php
print_r
($public_html);
/*
输出:
array(
"StudentFiles" => array (
"tutorial_01" => array (
"case1" => array( "file1.html", "file2.html")
),
"tutorial_02" => array (
"case1" => array( "file1.html"),
"case2" => array( "file2.html")
),
"tutorial_03" => array (
"case1" => array( "file2.html")
)
)
)
*/
?>
我用它来创建一个目录的树形视图。
phpguy at mailstop dot yogelements dot omitme dot com
17 年前
我遇到的一个问题是,`opendir()` 对子目录上的服务器身份验证并不关心,因此以这种方式访问时会完全绕过任何身份验证。我通过将所有子目录重定向到我的漂亮文件管理器应用程序中解决了这个问题
$fdir = "./subdirectory_I_want_to_visit/";
if ($fdir != './') { //基本上是我们所在的位置或父级
//重定向浏览器以强制对任何子目录进行身份验证检查
header("Location: http://my.domain.com".dirname($_SERVER["PHP_SELF"]).substr($fdir,2));
exit;
} else {
$dir = opendir($fdir);
}
Madog Llwyd
15 年前
一个简单的代码片段,用于打开一个目录并显示具有给定扩展名的所有文件。非常适合诸如新闻稿、评分表等情况,您只需让用户操作变得简单 - 他们只需将具有正确扩展名的文件放入其中,就完成了。会提供一个指向文件的链接,该链接会在新窗口中打开。

<?php
$current_dir
= "$DOCUMENT_ROOT"."dirname/"; //输入第二部分,即目录 - 不要加前导斜杠,但要加尾部斜杠!
$dir = opendir($current_dir); // 打开目录

echo ("<p><h1>List of available files:</h1></p><hr><br />");
while (
$file = readdir($dir)) // while 循环
{
$parts = explode(".", $file); // 将文件名拆解并按句点分割
if (is_array($parts) && count($parts) > 1) { // 拆解后的数组是否包含多个部分
$extension = end($parts); // 设置为我们可以查看最后一个文件扩展名
if ($extension == "ext" OR $extension == "EXT") // 扩展名是否为 ext 或 EXT?
echo "<a href=\"$file\" target=\"_blank\"> $file </a><br />"; // 如果是,则输出,否则不执行任何操作,因为这不是我们想要的
}
}
echo
"<hr><br />";
closedir($dir); // 我们完成后关闭目录
?>
kdouglas at satarah dot com
16 年前
广度优先搜索 (BFS) 用于查找文件或目录(与深度优先搜索相对)
http://en.wikipedia.org/wiki/Breadth-first_search

<?php

// 广度优先递归目录搜索,用于文件或目录
// 带有可选的屏蔽路径和可选的回调函数。
//
// $root -- 是搜索起始目录的相对路径
// $file -- 是完整的文件名:'name.ext' 例如:'data.xml'
// (或)$file -- 是目标目录名称 例如:'xml_files'
// $callback -- 是可选的函数名,并将传递所有
// 匹配的路径 例如:'my_func',而不是在第一次匹配时退出
// $omit -- 是可选的排除路径数组 - 相对于根目录
// 要使用 $omit 但不使用 $callback,请将 NULL 传递给 $callback 参数
//
// 测试值如下...

function my_func ( $path ) {
print
"<strong>$path</strong><br>\n";
}

$root = '../public_html';
$file = 'data.xml';
$callback = 'my_func';
$omit = array( 'include/img', 'include/css', 'scripts' );

//print breadth_first_file_search ( $root, $file );
//print breadth_first_file_search ( $root, $file, $callback );
//print breadth_first_file_search ( $root, $file, NULL, $omit );
print breadth_first_file_search ( $root, $file, $callback, $omit );

function
breadth_first_file_search ( $root, $file, $callback = NULL, $omit = array() ) {
$queue = array( rtrim( $root, '/' ).'/' ); // 规范化所有路径
foreach ( $omit as &$path ) { // &$path 需要 PHP 版本 5.x 及更高版本
$path = $root.trim( $path, '/' ).'/';
}
while (
$base = array_shift( $queue ) ) {
$file_path = $base.$file;
if (
file_exists( $file_path ) ) { // 找到文件
if ( is_callable( $callback ) ) {
$callback( $file_path ); // 回调 => 继续
} else {
return
$file_path; // 返回文件路径 => 退出
}
}
if ( (
$handle = opendir( $base ) ) ) {
while ( (
$child = readdir( $handle ) ) !== FALSE ) {
if (
is_dir( $base.$child ) && $child != '.' && $child != '..' ) {
$combined_path = $base.$child.'/';
if ( !
in_array( $combined_path, $omit ) ) {
array_push( $queue, $combined_path);
}
}
}
closedir( $handle );
}
// 否则无法打开目录 => 下一个子目录
}
return
FALSE; // 树的末尾,未找到文件
}

?>
micklweiss at gmx dot net
20 年前
我在示例 1 中遇到了一些小问题。opendir() 按文件最后访问时间列出文件。我试图按数字顺序打印目录中的文件。

解决方案:使用 scandir() 代替(php5)或将文件存储在数组中并对其进行排序。

希望这对某人有帮助。

- Mick

(o> Web/软件开发人员
( ) UNIX 系统管理员
--- ~ www.mickweiss.com ~
olivernassar.com
15 年前
希望这对其他人有帮助。返回目录及其所有子目录中的所有文件列表。
排除 $exempt 数组中的文件/文件夹。可以很容易地修改它,以便不会按引用传递文件。

<?php

function getFiles($directory,$exempt = array('.','..','.ds_store','.svn'),&$files = array()) {
$handle = opendir($directory);
while(
false !== ($resource = readdir($handle))) {
if(!
in_array(strtolower($resource),$exempt)) {
if(
is_dir($directory.$resource.'/'))
array_merge($files,
self::getFiles($directory.$resource.'/',$exempt,$files));
else
$files[] = $directory.$resource;
}
}
closedir($handle);
return
$files;
}

?>
lolwut
17 年前
我发现这有时很有用。希望你也会。

<?php
//list_by_ext: 返回一个数组,其中包含指定目录 ($path) 中文件的字母顺序列表,这些文件的文件扩展名与 $extension 匹配

function list_by_ext($extension, $path){
$list = array(); // 初始化一个变量
$dir_handle = @opendir($path) or die("无法打开 $path"); // 尝试打开路径
while($file = readdir($dir_handle)){ // 循环遍历路径中的所有文件
if($file == "." || $file == ".."){continue;} // 忽略这些
$filename = explode(".",$file); // 将文件名与扩展名分开
$cnt = count($filename); $cnt--; $ext = $filename[$cnt]; // 如上所述
if(strtolower($ext) == strtolower($extension)){ // 如果文件扩展名与我们正在查找的扩展名匹配...
array_push($list, $file); //... 然后将其粘贴到列表数组的末尾
}
}
if(
$list[0]){ //... 如果找到匹配项...
return $list; //... 返回数组
} else {// 否则...
return false;
}
}

// 示例用法
if($win32_exectuables = list_by_ext("exe", "C:\WINDOWS")){
var_dump($win32_exectuables);
} else {
echo
"未找到 Windows 可执行文件 :(\n";
}

?>
php at uchange dot co dot uk
15 年前
在花了大约一个小时尝试从 Windows 网络共享获取完整的文件列表后,我放弃了(Apache 2.2 Win32、WinXP、PHP5 -> Windows 2000 R2)。

尝试使用映射的驱动器号会给我一个错误,而尝试使用 UNC 路径可以工作,但速度非常慢(打开并读取包含数百个文件的目录需要几分钟)。

使用此代码速度很快,而且是即时的(您需要自己将输出分割,但就这样吧!)

$out = `dir $dir /B /S`;

如果您不需要递归子目录,请从命令中删除 /S - 有关更多详细信息,请在 Windows 上运行 'dir /?'。

希望这对遇到类似问题的其他人有帮助!
info at 4design dot nu
20 年前
除了上面关于 IIS & PHP 读取网络共享的说明外,这里还有一个对我来说效果更好的解决方案。

在管理控制台中,我创建了一个文件夹,我的 "read_dir" 脚本运行在其中。点击属性,然后选择安全选项卡。在这里,您可以将匿名帐户设置为标准的 IUSR_$computername% ,但是... 在这种情况下,我选择了另一个帐户,该帐户是我为读取我的共享设置的。(确保登录名和密码与您在远程计算机上设置的凭据匹配 ;-))

我用它来读取一个目录及其内容到一个可搜索的数据库中。它运行得很好...
匿名
18 年前
我只是想要一个目录列表和一个可点击的链接来下载文件,因为我的 Plesk 服务器没有提供此功能。我稍微修改了一下脚本。

来自脚本新手的衷心感谢

------
<?
echo ("<h1>目录概述:</h1>");

function getFiles($path) {
// 函数接受一个路径,并返回一个按关联数组(包含文件信息)进行数字索引的数组,
// 按文件名(不区分大小写)排序。如果两个文件在不区分大小写的情况下比较时相同,它们将按 readdir() 中呈现的顺序进行排序
// 相对彼此排序
$files = array();
$fileNames = array();
$i = 0;

if (is_dir($path)) {
if ($dh = opendir($path)) {
while (($file = readdir($dh)) !== false) {
if ($file == "." || $file == "..") continue;
$fullpath = $path . "/" . $file;
$fkey = strtolower($file);
while (array_key_exists($fkey,$fileNames)) $fkey .= " ";
$a = stat($fullpath);
$files[$fkey]['size'] = $a['size'];
if ($a['size'] == 0) $files[$fkey]['sizetext'] = "-";
else if ($a['size'] > 1024) $files[$fkey]['sizetext'] = (ceil($a['size']/1024*100)/100) . " K";
else if ($a['size'] > 1024*1024) $files[$fkey]['sizetext'] = (ceil($a['size']/(1024*1024)*100)/100) . " Mb";
else $files[$fkey]['sizetext'] = $a['size'] . " bytes";
$files[$fkey]['name'] = $file;
$files[$fkey]['type'] = filetype($fullpath);
$fileNames[$i++] = $fkey;
}
closedir($dh);
} else die ("无法打开目录: $path");
} else die ("路径不是目录: $path");
sort($fileNames,SORT_STRING);
$sortedFiles = array();
$i = 0;
foreach($fileNames as $f) $sortedFiles[$i++] = $files[$f];

return $sortedFiles;
}

$files = getFiles("./");
foreach ($files as $file) print "&nbsp;&nbsp;&nbsp;&nbsp;<b><a href=\"$file[name]\">$file[name]</a></b><br>\n";
?>
匿名
15 年前
如果你想遍历一个目录,可以看看 SPL DirectoryIterator
https://php.net/manual/class.directoryiterator.php
Richard Bronosky
15 年前
获取目录列表并对其排序的最简单方法是执行 exec() 到 ls(例如:'ls -t')。但是,这被认为是不安全的。我的托管公司最终发现我在这样做,所以这里是我最快的解决方案。(幸运的是,每个文件都是在名称末尾创建的,带有 Unix 时间戳,并且没有其他数字。)

<?php
#exec('ls -t ./images/motion_detection/', $files); # 他们禁止了 exec,所以我现在必须手动执行。
if ($handle = opendir('./images/motion_detection/')) {
$files=array();
while (
false !== ($file = readdir($handle))) {
$files[$file] = preg_replace('/[^0-9]/', '', $file); # 时间戳可能不唯一,文件名是唯一的。
}
closedir($handle);
arsort($files);
$files=array_keys($files);
}
?>

在你复制别人的臃肿的厨房水槽函数/类之前,请考虑一下你拥有什么,以及你真正需要什么。
mstabile75 at gmail dot com
18 年前
<?php
/* 以下函数将列出目录中的所有文件夹和文件
这是一个递归函数,它使用全局数组。全局数组是我在递归函数中使用数组的最简单方法
* 此函数对您要搜索的层级数没有限制。
* 数组结构是我使用的一种结构。
参数:
$startdir => 指定要从中开始的目录;格式:必须以“/”结尾
$searchSubdirs => True/false; 如果要搜索子目录,则为 True
$directoriesonly => True/false; 如果您只想返回目录,则为 True
$maxlevel => "all" 或一个数字;指定要搜索的目录层级数
$level => 整数;函数当前正在搜索的目录层级
*/
function filelist ($startdir="./", $searchSubdirs=1, $directoriesonly=0, $maxlevel="all", $level=1) {
// 列出您要忽略的目录/文件名
$ignoredDirectory[] = ".";
$ignoredDirectory[] = "..";
$ignoredDirectory[] = "_vti_cnf";
global
$directorylist; // 初始化全局数组
if (is_dir($startdir)) {
if (
$dh = opendir($startdir)) {
while ((
$file = readdir($dh)) !== false) {
if (!(
array_search($file,$ignoredDirectory) > -1)) {
if (
filetype($startdir . $file) == "dir") {
// 以您选择的任何方式构建您的目录数组;
// 添加您想要的其他文件详细信息。
$directorylist[$startdir . $file]['level'] = $level;
$directorylist[$startdir . $file]['dir'] = 1;
$directorylist[$startdir . $file]['name'] = $file;
$directorylist[$startdir . $file]['path'] = $startdir;
if (
$searchSubdirs) {
if (((
$maxlevel) == "all") or ($maxlevel > $level)) {
filelist($startdir . $file . "/", $searchSubdirs, $directoriesonly, $maxlevel, $level + 1);
}
}
} else {
if (!
$directoriesonly) {
// 如果要包含文件;以您选择的任何方式构建您的文件数组
// 添加您想要的其他文件详细信息。
$directorylist[$startdir . $file]['level'] = $level;
$directorylist[$startdir . $file]['dir'] = 0;
$directorylist[$startdir . $file]['name'] = $file;
$directorylist[$startdir . $file]['path'] = $startdir;
}}}}
closedir($dh);
}}
return(
$directorylist);
}
$files = filelist("./",1,1); // 调用函数
foreach ($files as $list) {// 打印数组
echo "Directory: " . $list['dir'] . " => Level: " . $list['level'] . " => Name: " . $list['name'] . " => Path: " . $list['path'] ."<br>";
}
?>
Michael mt1955 (a) gmail.com
17 年前
# 使用回调函数的简单目录遍历

<?php
function callbackDir($dir)
{
# 在这里执行您想执行的任何操作
echo "$dir\n";
}

function
walkDir($dir,$fx)
{
$arStack = array();
$fx($dir);
if( (
$dh=opendir($dir)) )
{ while( (
$file=readdir($dh))!==false )
{ if(
$file=='.' || $file=='..' ) continue;
if(
is_dir("$dir/$file") )
{ if( !
in_array("$dir/$file",$arStack) ) $arStack[]="$dir/$file";
}
}
closedir($dh);
}
if(
count($arStack) )
{ foreach(
$arStack as $subdir )
{
walkDir($subdir,$fx);
}
}
}

walkDir($root,callBackDir);
?>
To Top