你所尋找的是也被稱爲遞歸遍歷目錄。這意味着,您正在瀏覽所有目錄並列出其中的子目錄和文件。如果有一個子目錄被遍歷,等等等等 - 所以它是遞歸的。
正如你可以想象的那樣,當你編寫一個軟件並且PHP支持你時,這是你需要的常見事情。它提供了一個RecursiveDirectoryIterator
,以便可以遞歸迭代目錄,並使用標準RecursiveIteratorIterator
來執行遍歷。然後,您可以輕鬆地訪問所有文件和目錄用一個簡單的迭代,例如通過foreach
:
$rootpath = '.';
$fileinfos = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($rootpath)
);
foreach($fileinfos as $pathname => $fileinfo) {
if (!$fileinfo->isFile()) continue;
var_dump($pathname);
}
這個例子首先是指定要遍歷目錄。我一直在服用當前一個:
$rootpath = '.';
的下一行代碼是有點長,但它實例化the directory iterator然後the iterator-iterator使樹形結構可以在單一/平環遍歷:
$fileinfos = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($rootpath)
);
這些$fileinfos
然後用一個簡單的迭代foreach
:
foreach($fileinfos as $pathname => $fileinfo) {
內它有一個測試跳過所有目錄輸出。這是通過使用迭代的SplFileInfo
對象完成的。它由遞歸目錄迭代器提供,並且在處理文件時包含許多有用的屬性和方法。您還可以例如返回文件擴展名,關於大小和時間等的基本名稱信息等等。
if (!$fileinfo->isFile()) continue;
最後,我只輸出路徑這是完整的文件路徑:
var_dump($pathname);
示範性輸出應該是這樣的(這裏是Windows操作系統上):
string(12) ".\.buildpath"
string(11) ".\.htaccess"
string(33) ".\dom\xml-attacks\attacks-xml.php"
string(38) ".\dom\xml-attacks\billion-laughs-2.xml"
string(36) ".\dom\xml-attacks\billion-laughs.xml"
string(40) ".\dom\xml-attacks\quadratic-blowup-2.xml"
string(40) ".\dom\xml-attacks\quadratic-blowup-3.xml"
string(38) ".\dom\xml-attacks\quadratic-blowup.xml"
string(22) ".\dom\xmltree-dump.php"
string(25) ".\dom\xpath-list-tags.php"
string(22) ".\dom\xpath-search.php"
string(27) ".\dom\xpath-text-search.php"
string(29) ".\encrypt-decrypt\decrypt.php"
string(29) ".\encrypt-decrypt\encrypt.php"
string(26) ".\encrypt-decrypt\test.php"
string(13) ".\favicon.ico"
如果存在無法訪問的子目錄,則以下操作將引發異常。這種行爲可以通過一些標誌實例化RecursiveIteratorIterator
時進行控制:
$fileinfos = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator('.'),
RecursiveIteratorIterator::LEAVES_ONLY,
RecursiveIteratorIterator::CATCH_GET_CHILD
);
我希望這是信息。您也可以將其包裝到您自己的類中,也可以提供FilterIterator
以移動文件是否應列出或不在foreach
循環之外的決定。
的RecursiveDirectoryIterator
和RecursiveIteratorIterator
組合的力量散發出來的靈活性。以上沒有提到的是所謂的FilterIterator
。我想我補充了另一個利用兩個自己編寫的例子,將它們放置在一起以便合併它們。
- 一是篩選出以點開始(那些被認爲是UNIX系統上的隱藏文件,所以你不應該給這些信息外)和
- 另外一個是過濾所有的文件和目錄僅列出文件。那就是之前的這個檢查。
在此使用示例中的另一個變化是使用它返回迭代的ROOTPATH啓動子路徑的getSubPathname()
function的,所以一個你要尋找的。
而且我明確地添加,防止穿越.
和..
的SKIP_DOTS
flag(技術上沒有真的有必要因爲過濾器將過濾那些,以及他們是目錄,但我認爲這是比較正確的),並返回的路徑,UNIX_PATHS
這樣的路徑字符串是不管底層操作系統通常是,如果通過HTTP請求這些值後來由於你的情況是個好主意總是Unix類路徑:
$rootpath = '.';
$fileinfos = new RecursiveIteratorIterator(
new FilesOnlyFilter(
new VisibleOnlyFilter(
new RecursiveDirectoryIterator(
$rootpath,
FilesystemIterator::SKIP_DOTS
| FilesystemIterator::UNIX_PATHS
)
)
),
RecursiveIteratorIterator::LEAVES_ONLY,
RecursiveIteratorIterator::CATCH_GET_CHILD
);
foreach ($fileinfos as $pathname => $fileinfo) {
echo $fileinfos->getSubPathname(), "\n";
}
這個例子是類似以前一個雖然如何$fileinfos
構建是有點不同配置。特別是關於過濾器的部分是新的:
new FilesOnlyFilter(
new VisibleOnlyFilter(
new RecursiveDirectoryIterator($rootpath, ...)
)
),
因此,目錄迭代器被放入一個過濾器,並且過濾器本身被放入另一個過濾器。其餘的沒有改變。
的代碼,這些過濾器是非常簡單的,它們與accept
功能要麼是true
或false
這是採取或濾除工作:
class VisibleOnlyFilter extends RecursiveFilterIterator
{
public function accept()
{
$fileName = $this->getInnerIterator()->current()->getFileName();
$firstChar = $fileName[0];
return $firstChar !== '.';
}
}
class FilesOnlyFilter extends RecursiveFilterIterator
{
public function accept()
{
$iterator = $this->getInnerIterator();
// allow traversal
if ($iterator->hasChildren()) {
return true;
}
// filter entries, only allow true files
return $iterator->current()->isFile();
}
}
而這又是它。當然,您也可以將這些過濾器用於其他情況。例如。如果你有另一種目錄列表。
並與$rootpath
另一個示例性輸出切掉:
test.html
test.rss
tests/test-pad-2.php
tests/test-pad-3.php
tests/test-pad-4.php
tests/test-pad-5.php
tests/test-pad-6.php
tests/test-pad.php
TLD/PSL/C/dkim-regdom.c
TLD/PSL/C/dkim-regdom.h
TLD/PSL/C/Makefile
TLD/PSL/C/punycode.pl
TLD/PSL/C/test-dkim-regdom.c
TLD/PSL/C/test-dkim-regdom.sh
TLD/PSL/C/tld-canon.h
TLD/PSL/generateEffectiveTLDs.php
沒有更多.git
或.svn
目錄遍歷或類似.builtpath
或.project
文件的清單。
注意事項FilesOnlyFilter
和LEAVES_ONLY
: 過濾明確否認使用基於SplFileInfo
對象(only regular files that do exist)上的目錄和鏈接。所以這是一個基於文件系統的真正的過濾。
由於默認LEAVES_ONLY
flag(這裏也在示例中使用),另一種僅獲得非目錄條目的方法是RecursiveIteratorIterator
。該標誌不起濾波器的作用,獨立於底層迭代器。它只是指定迭代不應該返回分支(這裏:目錄的情況下,目錄迭代器)。
我明白你的文件夾結構,現在你想要輸出什麼,在你的問題中更新**所需的輸出** :) –
你爲什麼要這麼做。我沒有使用PHP的經驗,但在我看來,這會殺死你可憐的服務器。想象一下5000人正在讀你的目錄結構! – Tanmay
那麼爲什麼我想這樣做是因爲我有一個腳本在閃存as3,可以一次下載一個文件。 Flash無法下載文件夾及其內容,所以我想讓php創建一個包含文件夾/子文件夾所有內容的字符串,並將其發送回閃存,並且可以開始下載應用程序中的內容。 :) –