Php 无法使用RecursiveDirectoryIterator跳过不可读的目录
我想获得所有子目录的列表,我下面的代码可以工作,除非我对某些文件夹拥有只读权限 在下面的问题中,它展示了如何使用RecursiveDirectoryIterator跳过目录 然而,我的代码在这里略有不同,我无法回避这个问题Php 无法使用RecursiveDirectoryIterator跳过不可读的目录,php,directory,directory-walk,Php,Directory,Directory Walk,我想获得所有子目录的列表,我下面的代码可以工作,除非我对某些文件夹拥有只读权限 在下面的问题中,它展示了如何使用RecursiveDirectoryIterator跳过目录 然而,我的代码在这里略有不同,我无法回避这个问题 $path = 'www/'; foreach (new RecursiveIteratorIterator( new RecursiveDirectoryIterator($path,RecursiveDirectoryIterator::KEY_AS_PAT
$path = 'www/';
foreach (new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path,RecursiveDirectoryIterator::KEY_AS_PATHNAME),
RecursiveIteratorIterator::CHILD_FIRST) as $file => $info)
{
if ($info->isDir())
{
echo $file . '<br>';
}
}
我试着用另一个问题中被接受的答案来代替它
new RecursiveIteratorIterator(
new RecursiveDirectoryIterator("."),
RecursiveIteratorIterator::LEAVES_ONLY,
RecursiveIteratorIterator::CATCH_GET_CHILD);
但是,这段代码不会像我希望的那样给我一个www内所有目录的列表,我在这里哪里出错了?该函数自动跳过读取错误,并且应该简化您的代码。如果您遇到未经处理的异常,为什么不将该代码放在一个try块中,在无法读取目录时使用异常捕获块捕获错误?通过查看您的代码和问题,给出一个简单的建议。在PHP中可能有一种更简洁的方法 我已经设置了以下目录结构:
/
test.php <-- the test script
www/
test1/ <-- permissions = 000
file1
test2/
file2
file3
它的输出如下:
Array
(
[www/test2/file2] => SplFileInfo Object
(
[pathName:SplFileInfo:private] => www/test2/file2
[fileName:SplFileInfo:private] => file2
)
[www/file3] => SplFileInfo Object
(
[pathName:SplFileInfo:private] => www/file3
[fileName:SplFileInfo:private] => file3
)
)
这正如预期的那样有效
更新
添加了您在原始示例中使用的标志(尽管我认为这些是默认的):
如果要返回不可读的目录名,需要先使用
SELF\u
常量。
当您首先执行CHILD_
时,它试图进入目录,但失败,当前目录名不包括在内
$path = 'testing';
$directory_iterator = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_PATHNAME);
$iterator = new RecursiveIteratorIterator($directory_iterator,
RecursiveIteratorIterator::SELF_FIRST,
RecursiveIteratorIterator::CATCH_GET_CHILD);
foreach ($iterator as $file => $info) {
if ($info->isDir()) {
echo $file . "\n";
}
}
导言 代码的主要问题是先使用
CHILD\u
可选模式。可能的值是
- 递归迭代器::仅保留默认值。只列出迭代中的叶子
- RecursiveIteratorIterator::SELF_FIRST-列出迭代中的叶子和父母,父母排在第一位
- RecursiveIteratorIterator::CHILD_FIRST-列出迭代中的叶子和父母,叶子排在第一位
SELF\u
,以便包含当前目录。您还忘记添加可选参数recursiveiterator::CATCH\u GET\u CHILD
可选标志。可能的值是RecursiveIteratorIterator::CATCH_GET_CHILD,它将忽略调用RecursiveIteratorIterator::getChildren()时抛出的异常
重新访问您的代码
foreach (new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path,RecursiveDirectoryIterator::KEY_AS_PATHNAME),
RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD) as $file => $info)
{
if ($info->isDir())
{
echo $file . '<br>';
}
}
使用的类
class ReadableDirectoryIterator extends RecursiveFilterIterator {
function __construct($path) {
if (!$path instanceof RecursiveDirectoryIterator) {
if (! is_readable($path) || ! is_dir($path))
throw new InvalidArgumentException("$path is not a valid directory or not readable");
$path = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
}
parent::__construct($path);
}
public function accept() {
return $this->current()->isReadable() && $this->current()->isDir();
}
}
不如尝试捕获意外的ValueException。也许你甚至可以检查该错误的唯一异常代码。否则,您可以解析“权限被拒绝”的异常消息 我建议检查一下 此代码100%有效 您只需使用此功能即可扫描所需目录或驱动器中的文件和文件夹。您只需要将所需目录的路径传递到函数中。该函数的第二个参数是显示扫描文件和文件夹的完整路径。第二个参数的值为False表示不显示完整路径 数组$ignore用于从列表中排除任何所需的文件名或文件夹名 函数返回包含文件和文件夹列表的数组 此函数跳过递归时无法读取的文件和文件夹。
<?php
$path = "D:/Movies";
$directory_iterator = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_PATHNAME);
$files = new RecursiveIteratorIterator($directory_iterator,
RecursiveIteratorIterator::SELF_FIRST,
RecursiveIteratorIterator::CATCH_GET_CHILD);
try {
foreach( $files as $fullFileName => $file) {
$path_parts = pathinfo($fullFileName);
if(is_file($fullFileName)){
$path_parts = pathinfo($fullFileName);
$fileName[] = $path_parts['filename'];
$extensionName[] = $path_parts['extension'];
$dirName[] = $path_parts['dirname'];
$baseName[] = $path_parts['basename'];
$fullpath[] = $fullFileName;
}
}
foreach ($fullpath as $filles){
echo $filles;
echo "</br>";
}
}
catch (UnexpectedValueException $e) {
printf("Directory [%s] contained a directory we can not recurse into", $directory);
}
?>
如果它没有返回www中的所有目录,它会返回什么?它会返回目录,直到它得到一个它没有读取权限的目录,然后我得到错误,我希望能够跳过那些受限文件夹并返回目录中的所有其他文件夹。我确实查看了这些文件夹,谢谢,但无法获取www的子目录?您应该能够通过将glob pattern设置为***
来获取子目录。谢谢,这给了我一个数组中的结果,我需要进一步阅读迭代器\u to \u数组当我尝试将您的代码片段放入数组时,它会运行代码,但在初始测试时不会给出任何结果。@ak85当您以独立代码运行我的答案时会发生什么情况?我得到了数组,正如您所描述的,跳过了安全文件夹,但到目前为止,我无法将您的代码转换为我在示例。@ak85我已经更新了我的答案,以模仿您在问题开始时的回答;看看这对你是否有效。这看起来不错,我现在不在我的测试环境中,明天将确认。这段代码似乎生成了我所追求的格式folders@ak85肯定会的。。我只在第二个示例中添加了一个装饰器。。。而且效果很好。
$path = 'testing';
$directory_iterator = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_PATHNAME);
$iterator = new RecursiveIteratorIterator($directory_iterator,
RecursiveIteratorIterator::SELF_FIRST,
RecursiveIteratorIterator::CATCH_GET_CHILD);
foreach ($iterator as $file => $info) {
if ($info->isDir()) {
echo $file . "\n";
}
}
foreach (new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path,RecursiveDirectoryIterator::KEY_AS_PATHNAME),
RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD) as $file => $info)
{
if ($info->isDir())
{
echo $file . '<br>';
}
}
foreach ( new RecursiveIteratorIterator(
new ReadableDirectoryIterator($path),RecursiveIteratorIterator::CHILD_FIRST) as $file ) {
echo $file . '<br>';
}
class ReadableDirectoryIterator extends RecursiveFilterIterator {
function __construct($path) {
if (!$path instanceof RecursiveDirectoryIterator) {
if (! is_readable($path) || ! is_dir($path))
throw new InvalidArgumentException("$path is not a valid directory or not readable");
$path = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
}
parent::__construct($path);
}
public function accept() {
return $this->current()->isReadable() && $this->current()->isDir();
}
}
function dirScan($dir, $fullpath = false){
$ignore = array(".","..");
if (isset($dir) && is_readable($dir)){
$dlist = array();
$dir = realpath($dir);
$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir,RecursiveDirectoryIterator::KEY_AS_PATHNAME),RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD);
foreach($objects as $entry){
if(!in_array(basename($entry), $ignore)){
if (!$fullpath){
$entry = str_replace($dir, '', $entry);
}
$dlist[] = $entry;
}
}
return $dlist;
}
}
<?php
$path = "D:/Movies";
$directory_iterator = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_PATHNAME);
$files = new RecursiveIteratorIterator($directory_iterator,
RecursiveIteratorIterator::SELF_FIRST,
RecursiveIteratorIterator::CATCH_GET_CHILD);
try {
foreach( $files as $fullFileName => $file) {
$path_parts = pathinfo($fullFileName);
if(is_file($fullFileName)){
$path_parts = pathinfo($fullFileName);
$fileName[] = $path_parts['filename'];
$extensionName[] = $path_parts['extension'];
$dirName[] = $path_parts['dirname'];
$baseName[] = $path_parts['basename'];
$fullpath[] = $fullFileName;
}
}
foreach ($fullpath as $filles){
echo $filles;
echo "</br>";
}
}
catch (UnexpectedValueException $e) {
printf("Directory [%s] contained a directory we can not recurse into", $directory);
}
?>