php PHP获取文件夹/子文件夹中每个文件的路径到数组中?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12233859/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP get path to every file in folder/subfolder into array?
提问by Papa De Beau
Possible Duplicate:
PHP SPL RecursiveDirectoryIterator RecursiveIteratorIterator retrieving the full tree
可能的重复:
PHP SPL RecursiveDirectoryIterator RecursiveIteratorIterator 检索完整树
I am not sure where to start. But I have to get the paths to all files in a folder and all the content of the subfolder in paths too. For example if I had 1 folder that had five folders and each folder had 10 mp3s in it etc... That means my array would have to find 50 paths to these files.
我不知道从哪里开始。但是我必须获取文件夹中所有文件的路径以及路径中子文件夹的所有内容。例如,如果我有 1 个文件夹,其中有五个文件夹,每个文件夹中有 10 个 mp3 等等……这意味着我的数组必须找到这些文件的 50 个路径。
Later lets say I added one more folder and it had 3 folders in it and each folder had 10 images.
稍后可以说我又添加了一个文件夹,其中有 3 个文件夹,每个文件夹有 10 个图像。
My code would now need to find 80 paths and store them in an array.
我的代码现在需要找到 80 条路径并将它们存储在一个数组中。
Does my question make sense?
我的问题有意义吗?
UPDATE:
更新:
My desired out put would be to have all these paths stored in one array.
我想要的输出是将所有这些路径存储在一个数组中。
But I would "LOVE" the code to be dynamic, meaning if I later add 10 more folder and each having 17 subfolder and each folder having a multitude of different content. I would like the array to hold the file paths of all the files. I hppe this makes sense.
但我希望代码是动态的,这意味着如果我以后再添加 10 个文件夹,每个文件夹都有 17 个子文件夹,每个文件夹都有许多不同的内容。我希望数组保存所有文件的文件路径。我认为这是有道理的。
回答by hakre
What you are looking for is also called recursive directory traversing. Which means, you're going through all directories and list subdirectories and files in there. If there is a subdirectory it is traversed as well and so on and so forth - so it is recursive.
您正在寻找的也称为递归目录遍历。这意味着,您将浏览所有目录并列出其中的子目录和文件。如果有一个子目录,它也会被遍历等等——所以它是递归的。
As you can imagine this is somewhat a common thing you need when you write a software and PHP supports you with that. It offers one RecursiveDirectoryIteratorso that directories can be recursively iterated and the standard RecursiveIteratorIteratorto do the traversal. You can then easily access all files and directories with a simple iteration, for example via foreach:
正如您可以想象的那样,当您编写软件并且 PHP 支持您时,这在某种程度上是您需要的常见事情。它提供了一个RecursiveDirectoryIterator以便目录可以递归迭代和RecursiveIteratorIterator进行遍历的标准。然后,您可以通过简单的迭代轻松访问所有文件和目录,例如通过foreach:
$rootpath = '.';
$fileinfos = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($rootpath)
);
foreach($fileinfos as $pathname => $fileinfo) {
if (!$fileinfo->isFile()) continue;
var_dump($pathname);
}
This example first of all specifies the directory you want to traverse. I've been taking the current one:
这个例子首先指定了你要遍历的目录。我一直在服用当前的:
$rootpath = '.';
The next line of code is a little bit long, it does instantiate the directory iteratorand then the iterator-iteratorso that the tree-like structure can be traversed in a single/flat loop:
下一行代码有点长,它先实例化目录迭代器,然后实例化迭代器-迭代器,以便可以在单个/平面循环中遍历树状结构:
$fileinfos = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($rootpath)
);
These $fileinfosare then iterated with a simple foreach:
$fileinfos然后用一个简单的迭代它们foreach:
foreach($fileinfos as $pathname => $fileinfo) {
Inside of it, there is a test to skip all directories from being output. This is done by using the SplFileInfoobject that is iterated over. It is provided by the recursive directory iterator and contains a lot of helpful properties and methods when working with files. You can as well for example return the file extension, the basename information about size and time and so on and so forth.
在其中,有一个测试可以跳过所有目录的输出。这是通过使用SplFileInfo迭代的对象来完成的。它由递归目录迭代器提供,在处理文件时包含许多有用的属性和方法。例如,您还可以返回文件扩展名、有关大小和时间的基本名称信息等等。
if (!$fileinfo->isFile()) continue;
Finally I just output the pathnamethat is the full path to the file:
最后,我只输出作为文件完整路径的路径名:
var_dump($pathname);
An exemplary output would look like this (here on a windows operating system):
示例输出如下所示(此处为 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"
If there is a subdirectory that is not accessible, the following would throw an exception. This behaviour can be controlled with some flags when instantiating the RecursiveIteratorIterator:
如果存在不可访问的子目录,以下将引发异常。在实例化 时,可以使用一些标志来控制此行为RecursiveIteratorIterator:
$fileinfos = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator('.'),
RecursiveIteratorIterator::LEAVES_ONLY,
RecursiveIteratorIterator::CATCH_GET_CHILD
);
I hope this was informative. You can also Wrap this up into a class of your own and you can also provide a FilterIteratorto move the decision whether a file should be listed or not out of the foreachloop.
我希望这是有益的。您还可以将其打包到您自己的类中,您还可以提供一个FilterIterator来决定是否应列出文件foreach。
The power of the RecursiveDirectoryIteratorand RecursiveIteratorIteratorcombination comes out of its flexibility. What was not covered above are so called FilterIterators. I thought I add another example that is making use of two self-written of them, placed into each other to combine them.
RecursiveDirectoryIterator和RecursiveIteratorIterator组合的强大之处在于其灵活性。以上未涵盖的内容称为FilterIterators。我想我添加了另一个示例,该示例使用两个自己编写的示例,将它们放在一起以组合它们。
- One is to filter out all files and directories that start with a dot (those are considered hidden files on UNIX systems so you should not give that information to the outside) and
- Another one that is filtering the list to files only. That is the check that previously was insidethe foreach.
- 一种是过滤掉所有以点开头的文件和目录(它们在 UNIX 系统上被认为是隐藏文件,因此您不应将该信息提供给外部)和
- 另一个将列表过滤为仅文件。那是之前在foreach 中的检查。
Another change in this usage example is to make use of the getSubPathname()functionthat returns the subpath starting from the iteration's rootpath, so the one you're looking for.
此用法示例中的另一个更改是利用返回从迭代的根路径开始的子路径的getSubPathname()函数,即您正在寻找的子路径。
Also I explicitly add the SKIP_DOTSflagwhich prevents traversing .and ..(technically not reallynecessary because the filters would filter those as well as they are directories, however I think it is more correct) and return as paths as UNIX_PATHSso the strings of paths are always unix-like paths regardless of the underlying operating system Which is normally a good idea if those values are requested via HTTP later as in your case:
此外,我明确添加了防止遍历的SKIP_DOTS标志,.并且..(从技术上讲并不是真正必要的,因为过滤器会过滤它们以及它们是目录,但是我认为它更正确)并作为路径返回,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";
}
This example is similar to the previous one albeit how the $fileinfosis build is a little differently configured. Especially the part about the filters is new:
此示例与前一个示例类似,尽管$fileinfosis build 的配置方式略有不同。特别是关于过滤器的部分是新的:
new FilesOnlyFilter(
new VisibleOnlyFilter(
new RecursiveDirectoryIterator($rootpath, ...)
)
),
So the directory iterator is put into a filter and the filter itself is put into another filter. The rest did not change.
所以目录迭代器被放入一个过滤器,过滤器本身被放入另一个过滤器。其余没有变化。
The code for these filters is pretty straight forward, they work with the acceptfunction that is either trueor falsewhich is to take or to filter out:
这些过滤器的代码非常简单,它们与以下任一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();
}
}
And that's it again. Naturally you can use these filters for other cases, too. E.g. if you have another kind of directory listing.
又是这样。当然,您也可以将这些过滤器用于其他情况。例如,如果您有另一种目录列表。
And another exemplary output with the $rootpathcut away:
另一个示例性的输出被$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
No more .gitor .svndirectory traversal or listing of files like .builtpathor .project.
没有更多.git或.svn目录遍历或类似的文件列表.builtpath或.project。
Note for
FilesOnlyFilterandLEAVES_ONLY:The filter explicitly denies the use of directories andlinks based on theSplFileInfoobject (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 withRecursiveIteratorIteratorbecause of the defaultLEAVES_ONLYflag(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).
注意
FilesOnlyFilter和LEAVES_ONLY:过滤器明确拒绝使用基于对象的目录和链接SplFileInfo(只有确实存在的常规文件)。所以它是一个真正的基于文件系统的过滤。由于默认标志(这里也在示例中使用),
另一种仅获取非目录条目的方法随附。此标志不用作过滤器,并且独立于底层迭代器。它只是指定迭代不应返回分支(此处:目录迭代器的目录)。RecursiveIteratorIteratorLEAVES_ONLY
回答by msEmmaMays
If you are on linux and you don't mind executing a shell command, you can do this all in one line
如果您使用的是 linux 并且不介意执行 shell 命令,则可以在一行中完成所有操作
$path = '/etc/php5/*'; // file filter, you could specify a extension using *.ext
$files = explode("\n", trim(`find -L $path`)); // -L follows symlinks
print_r($files);
Output:
输出:
Array (
[0] => /etc/php5/apache2
[1] => /etc/php5/apache2/php.ini
[2] => /etc/php5/apache2/conf.d
[3] => /etc/php5/apache2/conf.d/gd.ini
[4] => /etc/php5/apache2/conf.d/curl.ini
[5] => /etc/php5/apache2/conf.d/mcrypt.ini
etc...
)
The next shortest choice using only PHP is glob- but it doesn't scan sub-directories like you want. (you'd have to loop through the results, use is_dir() and then call your function again
仅使用 PHP 的下一个最短选择是 glob- 但它不会像您想要的那样扫描子目录。(您必须遍历结果,使用 is_dir() 然后再次调用您的函数
$files = dir_scan('/etc/php5/*');
print_r($files);
function dir_scan($folder) {
$files = glob($folder);
foreach ($files as $f) {
if (is_dir($f)) {
$files = array_merge($files, dir_scan($f .'/*')); // scan subfolder
}
}
return $files;
}
Every other way requires way more code then should be necessary to do something so simple
所有其他方式都需要更多的代码,然后应该有必要做一些如此简单的事情
回答by Tanmay
Steps are as such:
步骤如下:
and opendir will open the directory structure
和 opendir 将打开目录结构
$dh = opendir($dir)
$dh = opendir($dir)
what you do next is read whatever is there in $dh
你接下来要做的是阅读里面有什么 $dh
$file = readdir($dh)
$file = readdir($dh)
you can find all the info in the php manual corresponding to opendir
您可以在对应的php手册中找到所有信息 opendir
and googling for reading the structure returned this
并通过谷歌搜索阅读结构返回了这个

