僅供參考,對於在 2.6.31 和更新的內核上遇到 is_dir() 在 CIFS 掛載點或這些掛載點內的目錄上返回 false 的任何人:顯然在新內核中,他們開始預設使用 CIFS serverino 選項。對於 Windows 共享,這會導致大量的 inode 編號,這顯然會導致 is_dir() 返回 false。將 noserverino 選項添加到 CIFS 掛載將防止這種情況發生。這可能只發生在 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 和更新的內核上遇到 is_dir() 在 CIFS 掛載點或這些掛載點內的目錄上返回 false 的任何人:顯然在新內核中,他們開始預設使用 CIFS serverino 選項。對於 Windows 共享,這會導致大量的 inode 編號,這顯然會導致 is_dir() 返回 false。將 noserverino 選項添加到 CIFS 掛載將防止這種情況發生。這可能只發生在 32 位系統上,但我沒有 64 位安裝可以測試。
這是我用來解決問題的 "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);
}
我不記得它是從哪裡來的,但它運作良好。
我對於「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 代表檔案
}
// 顯示項目編號、項目類型 (D/F) 和項目名稱
echo '<br>'.$i.'. '. $MyFileType[$i].'. ' .$files[$i] ;
$i++;
}
?>
處理子目錄時的陷阱
在處理子目錄時遇到問題(有些子目錄被跳過)並閱讀了相關文章後,我發現幾乎沒有人清楚地說明錯誤所在。
常見的遍歷目錄程式碼如下:
-----------------------------------------
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; // 跳過子目錄
真正的陷阱是,在沒有完整路徑的情況下,仍然可以找到一些子目錄...希望這能釐清一切
當我在 Win32 平台(Win XP SP3、Apache/2.2.11、PHP/5.2.9)上嘗試列舉掛載的磁碟機(未使用 'pear')時,我使用了以下程式碼:
<?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 的一個 bug,或者更精確地說,是一個限制。請參考 http://bugs.php.net/bug.php?id=27792
該頁面上(上方連結)發布了一個解決方法,對我來說似乎有效
function is_dir_LFS($path){
return (('d'==substr(exec("ls -dl '$path'"),0,1))?(true):(false));
}
備註:我使用的是 PHP 4.3.10-16,據回報這個問題最高到 5.0 版都有。
在 Apache Windows 上運行 PHP 5.2.0 時,我遇到了一個問題(可能與其他人描述的相同),即使某些目錄可以訪問,is_dir 也會傳回 False。
奇怪的是,我可以透過更完整的路徑來解決這個問題。例如,這只會在具有特定權限的子目錄上顯示「Works」(在此目錄中,大約三分之一的目錄會出現這個問題)
$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) ? '空' : '非空';
?>
這個函式可以繞過 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");
?>
輸出
警告:open_basedir 限制生效中
<?
....
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 "檔案名稱:" . $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" 檔案計入!
一個更好的(僅限 PHP 5)替代 "Davy Defaud 的函式" 的方法
<?php
function is_empty_dir($dir)
{
if (($files = @scandir($dir)) && count($files) <= 2) {
return true;
}
return false;
}
?>
注意:您顯然應該事先檢查 $dir 是否實際上是一個目錄,以及它是否可讀,因為僅依賴於此,您會假設在這兩種情況下,您都有一個非空的、可讀的目錄。
遺憾的是,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;
}
<?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;
}
?>