这个问题在这里已经有了答案:
9年前关闭。
Possible Duplicate:
PHP SPL RecursiveDirectoryIterator RecursiveIteratorIterator retrieving the full tree
我不知道从哪里开始。但是我必须获取文件夹中所有文件的路径以及路径中子文件夹的所有内容。例如,如果我有 1 个文件夹,其中有五个文件夹,每个文件夹中有 10 个 mp3 等等……这意味着我的数组必须找到这些文件的 50 个路径。
稍后可以说我又添加了一个文件夹,其中有 3 个文件夹,每个文件夹有 10 个图像。
我的代码现在需要找到 80 条路径并将它们存储在一个数组中。
我的问题有意义吗?
更新:
我想要的输出是将所有这些路径存储在一个数组中。
但我希望代码是动态的,这意味着如果我以后再添加 10 个文件夹,每个文件夹都有 17 个子文件夹,每个文件夹都有许多不同的内容。我希望数组保存所有文件的文件路径。我认为这是有道理的。
最佳答案
您正在寻找的也称为递归目录遍历。这意味着,您将浏览所有目录并列出其中的子目录和文件。如果有一个子目录,它也会被遍历等等——所以它是递归的。
正如您可以想象的那样,当您编写软件并且 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
s。我想我添加了另一个示例,该示例使用两个自己编写的示例,将它们放在一起以组合它们。此用法示例的另一个更改是使用
getSubPathname()
function它返回从迭代的根路径开始的子路径,所以你正在寻找。我还明确添加了
SKIP_DOTS
flag这可以防止遍历 .
和 ..
(从技术上讲并不是真的有必要,因为过滤器会过滤它们以及它们是目录,但是我认为它更正确)并作为路径返回 UNIX_PATHS
因此,无论底层操作系统如何,路径字符串始终是类 Unix 路径,如果稍后通过 HTTP 请求这些值(如您的情况),这通常是一个好主意:$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
build 的配置略有不同。特别是关于过滤器的部分是新的: 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
.Note for
FilesOnlyFilter
andLEAVES_ONLY
: The filter explicitly denies the use of directories and links based on theSplFileInfo
object (only regular files that do exist). So it is a real filtering based on the file-system.
Another method to only get non-directory entries ships withRecursiveIteratorIterator
because of the defaultLEAVES_ONLY
flag (here used too in the examples). This flag does not work as a filter and is independent to the underlying iterator. It just specifies that the iteration should not return branchs (here: directories in case of the directory iterator).
关于PHP获取文件夹/子文件夹中每个文件的路径到数组中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12233859/