对于在 2.6.31 及更高内核上遇到 CIFS 挂载点或这些挂载点内目录的 is_dir() 返回 false 的任何人,请注意:显然在新内核中,他们已默认开始使用 CIFS serverino 选项。使用 Windows 共享会导致巨大的 inode 号码,这显然会导致 is_dir() 返回 false。在 CIFS 挂载中添加 noserverino 选项将阻止这种情况。这可能只发生在 32 位系统上,但我没有 64 位安装可以进行测试。
(PHP 4, PHP 5, PHP 7, PHP 8)
is_dir — 判断文件名是否为目录
filename
文件路径。如果 filename
是相对文件名,则将相对于当前工作目录进行检查。如果 filename
是符号链接或硬链接,则将解析链接并进行检查。如果您已启用 open_basedir,则可能适用进一步的限制。
失败时,将发出 E_WARNING
。
示例 #1 is_dir() 示例
<?php
var_dump(is_dir('a_file.txt'));
var_dump(is_dir('bogus_dir/abc'));
var_dump(is_dir('..')); // 上一级目录
?>
以上示例将输出
bool(false) bool(false) bool(true)
注意: 此函数的结果被缓存。有关更多详细信息,请参阅 clearstatcache()。
对于在 2.6.31 及更高内核上遇到 CIFS 挂载点或这些挂载点内目录的 is_dir() 返回 false 的任何人,请注意:显然在新内核中,他们已默认开始使用 CIFS serverino 选项。使用 Windows 共享会导致巨大的 inode 号码,这显然会导致 is_dir() 返回 false。在 CIFS 挂载中添加 noserverino 选项将阻止这种情况。这可能只发生在 32 位系统上,但我没有 64 位安装可以进行测试。
我针对您必须包含完整路径才能使“is_dir”正常工作的问题的解决方案,作为完整的示例
<? // findfiles.php - videoarchive 目录中的内容
$dir = 'images/videoarchive/'; // 从顶部开始的路径
$files = scandir($dir);
$files_n = count($files);
$i=0;
while($i<=$files_n){
// “is_dir” 只从顶级目录起作用,因此在文件之前附加 $dir
if (is_dir($dir.'/'.$files[$i])){
$MyFileType[$i] = "D" ; // D 代表目录
} else{
$MyFileType[$i] = "F" ; // F 代表文件
}
// 打印 itemNo、itemType(D/F) 和 itemname
echo '<br>'.$i.'. '. $MyFileType[$i].'. ' .$files[$i] ;
$i++;
}
?>
这是我用来解决问题的“is_dir”函数
function Another_is_dir ($file)
{
if ((fileperms("$file") & 0x4000) == 0x4000)
return TRUE;
else
return FALSE;
}
或者,更简单
function Another_is_dir ($file)
{
return ((fileperms("$file") & 0x4000) == 0x4000);
}
我不记得它来自哪里,但它工作正常。
子目录处理中的陷阱
在苦苦挣扎于子目录处理(一些子目录被跳过)并阅读了帖子后,我意识到几乎没有人清楚地说明了问题所在。
常见的遍历目录代码是
-----------------------------------------
opendir("myphotos"); // 要从其开始处理的顶级目录(示例)
while (false !== ($fname = readdir($h_dir))) { // 处理当前目录(读取目录条目)
if ($fname{0} == '.') continue; // 使用第一个字符测试跳过 . 和 .. 目录
if (is_dir($fname)) call_own_subdir_process; // 通过调用例程来处理此子目录
}
问题是
“is_dir()” 必须具有完整路径,否则它将跳过一些目录。因此,上面的代码需要在文件名之前插入路径。这将在上面进行以下更改...
if (is_dir("myphotos\" . $fname)) call_own_subdir_process; // 跳过子目录
陷阱确实在于,如果没有完整路径,一些子目录会被找到...希望这能澄清一切
在尝试(没有“pear”)枚举 win32 平台上的挂载驱动器时(Win XP SP3、Apache/2.2.11、PHP/5.2.9),我使用了
<?php
function echo_win_drives() {
for($c='A'; $c<='Z'; $c++)
if(is_dir($c . ':'))
echo $c . ': ';
}
?>
这产生了
A: C: D: E: F: G: H: I
啊哈!也许这是 php 的一个错误或局限性。参见 http://bugs.php.net/bug.php?id=27792
该页面(上方)上发布了一个解决方法,它似乎对我有用
function is_dir_LFS($path){
return (('d'==substr(exec("ls -dl '$path'"),0,1))?(true):(false));
}
PS: 我使用的是 PHP 4.3.10-16,帖子报告了这个问题一直到 5.0
我在 Apache Windows 上运行 PHP 5.2.0,遇到一个问题(很可能与其他人描述的问题相同),即 is_dir 对于具有特定权限的目录返回 False,即使它们是可访问的。
奇怪的是,我能够通过更完整的路径来克服这个问题。例如,这只会显示具有特定权限的子目录的“Works”(在此目录中约为 3 个中的 1 个)
$d = opendir("./albums/mydir");
while(false !== ($f = readdir($d))) {
echo "<hr />";
if(is_dir($f)) {
echo "<b>Works:" . $f . "</b>";
}
}
然而,这对所有目录都正常工作
$d = opendir("./albums/mydir");
while(false !== ($f = readdir($d))) {
echo "<hr />";
$dName = "./albums/mydir/" . $f;
if(is_dir($dName)) {
echo "<b>Works:" . $dName . "</b>";
}
}
我不理解第一段代码的命中和未命中,但也许第二段代码可以帮助其他人遇到这个问题。
关于检查空目录的一个注释
>>echo (count(glob("$dir/*")) === 0) ? 'Empty' : 'Not empty';
这在 Linux 上不起作用。
即使目录中没有文件,也会始终返回“.” 和“..”。
请注意,is_dir() 函数也适用于 ftp://.
例如
<?php
if(is_dir('ftp://user:pass@host/www/path/to/your/folder')) {
// 您的代码。
}
?>
但请注意,如果由于无效凭据导致连接失败,这将被视为文件夹不存在,并返回 FALSE。
请注意,此函数会跟踪符号链接。如果文件实际上是指向目录的符号链接,它将返回 true。
一个例子
<php
symlink(".", "testlink");
var_dump(is_dir("testlink"));
unlink("testlink");
?>
输出
bool(true)
(Windows 注意:在最新版本的 Windows 中,只要您是管理员,就可以设置符号链接,但不能使用 “unlink()” 删除目录符号链接,您必须使用 shell 中的 “rmdir testlink” 来删除它。)
这里还有另一种测试目录是否为空的方法,我认为比下面发布的方法简单得多
<?php
$dir = 'directory';
echo (count(glob("$dir/*")) === 0) ? 'Empty' : 'Not empty';
?>
此函数绕过 open_basedir 限制。
<?
function my_is_dir($dir)
{
// 绕过 is_dir 和 fileperms 的 open_basedir 限制
$tmp_cmd = `ls -dl $dir`;
$dir_flag = $tmp_cmd[0];
if($dir_flag!="d")
{
// 不是 d;使用下一个字符(第一个字符可能是 's',但仍然是目录)
$dir_flag = $tmp_cmd[1];
}
return ($dir_flag=="d");
}
?>
例子
<?
....
echo is_dir("/somewhere/i/dont/have/access/to");
?>
输出
Warning: open_basedir restriction in effect
<?
....
echo my_is_dir("/somewhere/i/dont/have/access/to");
?>
输出
true(或 false,取决于它是否真的存在...)
---
访问 puremango.co.uk 获取其他类似的奇观
请注意,网络上有很多文章暗示像 is_dir、opendir、readdir 这样的命令无法读取包含空格的路径。
在 Linux 系统上,这不是问题。
示例测试代码;
$dir = "Images/Soma ALbum Name with spaces";
echo $dir."<br/>";
// 打开一个目录,并读取它的内容
if (is_dir($dir)){
echo $dir."<br/>"; // 如果上面失败,则不会出现
if ($dh = opendir($dir)){
echo $dir."<br/>"; // 如果上面失败,则不会出现
while (($file = readdir($dh)) !== false){
echo "filename:" . $file . "<br>";
echo $dir."<br/>"; // 如果上面失败,则不会出现
}
closedir($dh);
}
}
如果您使用的是 Mac 或其他存储有关目录布局等信息的系统,则函数
function empty_dir($dir) {
if (($files = @scandir($dir)) && count($files) <= 3)
return true;
else
return false;
}
必须让 count($files) 与隐藏文件的数量进行比较!
例如,我使用的是 Mac,空目录显示给我三个文件:“.”,“..” 和 “.DS_Store”,所以如果我打算在我的 Mac 上将网站上线,我需要将 “.DS_Store” 文件计算在内!
一个比“Davy Defaud 的函数”更好的 (仅限 PHP 5) 替代方法
<?php
function is_empty_dir($dir)
{
if (($files = @scandir($dir)) && count($files) <= 2) {
return true;
}
return false;
}
?>
注意:您显然应该事先检查 $dir 是否确实是一个目录,以及它是否可读,因为只依赖它,您将假设在两种情况下您都有一个非空的可读目录。
<?php
public static function isEmptyDir($dir){
return (($files = @scandir($dir)) && count($files) <= 2);
}
?>
更好 ;)
使用此函数获取目录中的所有文件(包括子目录)
<?php
function scan_Dir($dir) {
$arrfiles = array();
if (is_dir($dir)) {
if ($handle = opendir($dir)) {
chdir($dir);
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
if (is_dir($file)) {
$arr = scan_Dir($file);
foreach ($arr as $value) {
$arrfiles[] = $dir."/".$value;
}
} else {
$arrfiles[] = $dir."/".$file;
}
}
}
chdir("../");
}
closedir($handle);
}
return $arrfiles;
}
?>
不幸的是,p dot marzec at bold-sg dot pl 发布的函数无法正常工作。
修正后的版本是
// 如果文件夹为空或不存在,则返回 true
// 如果文件夹已满,则返回 false
function is_empty_folder($dir) {
if (is_dir($dir)) {
$dl=opendir($dir);
if ($dl) {
while($name = readdir($dl)) {
if (!is_dir("$dir/$name")) { //<--- 这里已修正
return false;
break;
}
}
closedir($dl);
}
return true;
} else return true;
}
当我运行 scandir 时,我总是运行一个简单的过滤器来处理文件系统伪影(尤其是来自简单的 FTP 文件夹放置)以及每个目录中出现的 “.” “..”
<?php
if (is_dir($folder){
$contents = scandir($folder);
$bad = array(".", "..", ".DS_Store", "_notes", "Thumbs.db");
$files = array_diff($contents, $bad);
}
?>