php 使用PHP递归函数列出目录中的所有文件和文件夹
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24783862/
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
List all the files and folders in a Directory with PHP recursive function
提问by user3412869
I'm trying to go through all of the files in a directory, and if there is a directory, go through all of its files and so on until there are no more directories to go to. Each and every processed item will be added to a results array in the function below. It is not working though I'm not sure what I can do/what I did wrong, but the browser runs insanely slow when this code below is processed, any help is appreciated, thanks!
我正在尝试浏览目录中的所有文件,如果有目录,则浏览其所有文件,依此类推,直到没有更多目录可供访问。每个处理过的项目都将添加到下面函数中的结果数组中。虽然我不确定我能做什么/我做错了什么,但它不起作用,但是当处理下面的代码时,浏览器运行速度非常慢,感谢任何帮助,谢谢!
Code:
代码:
function getDirContents($dir){
$results = array();
$files = scandir($dir);
foreach($files as $key => $value){
if(!is_dir($dir. DIRECTORY_SEPARATOR .$value)){
$results[] = $value;
} else if(is_dir($dir. DIRECTORY_SEPARATOR .$value)) {
$results[] = $value;
getDirContents($dir. DIRECTORY_SEPARATOR .$value);
}
}
}
print_r(getDirContents('/xampp/htdocs/WORK'));
回答by A-312
Get all the files and folders in a directory, don't call function when you have .
or ..
.
获取目录中的所有文件和文件夹,当你有.
或时不要调用函数..
。
Your code :
你的代码:
<?php
function getDirContents($dir, &$results = array()) {
$files = scandir($dir);
foreach ($files as $key => $value) {
$path = realpath($dir . DIRECTORY_SEPARATOR . $value);
if (!is_dir($path)) {
$results[] = $path;
} else if ($value != "." && $value != "..") {
getDirContents($path, $results);
$results[] = $path;
}
}
return $results;
}
var_dump(getDirContents('/xampp/htdocs/WORK'));
Output (example) :
输出(示例):
array (size=12)
0 => string '/xampp/htdocs/WORK/iframe.html' (length=30)
1 => string '/xampp/htdocs/WORK/index.html' (length=29)
2 => string '/xampp/htdocs/WORK/js' (length=21)
3 => string '/xampp/htdocs/WORK/js/btwn.js' (length=29)
4 => string '/xampp/htdocs/WORK/js/qunit' (length=27)
5 => string '/xampp/htdocs/WORK/js/qunit/qunit.css' (length=37)
6 => string '/xampp/htdocs/WORK/js/qunit/qunit.js' (length=36)
7 => string '/xampp/htdocs/WORK/js/unit-test.js' (length=34)
8 => string '/xampp/htdocs/WORK/xxxxx.js' (length=30)
9 => string '/xampp/htdocs/WORK/plane.png' (length=28)
10 => string '/xampp/htdocs/WORK/qunit.html' (length=29)
11 => string '/xampp/htdocs/WORK/styles.less' (length=30)
回答by zkanoca
$rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('path/to/folder'));
$files = array();
foreach ($rii as $file) {
if ($file->isDir()){
continue;
}
$files[] = $file->getPathname();
}
var_dump($files);
This will bring you all the files with paths.
这将为您带来所有带路径的文件。
回答by A-312
It's shorter version :
这是较短的版本:
function getDirContents($path) {
$rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));
$files = array();
foreach ($rii as $file)
if (!$file->isDir())
$files[] = $file->getPathname();
return $files;
}
var_dump(getDirContents($path));
回答by A-312
Get all the files with filter(2nd argument)and folders in a directory, don't call function when you have .
or ..
.
获取目录中带有过滤器(第二个参数)和文件夹的所有文件,当您有.
或时不要调用函数..
。
Your code :
你的代码:
<?php
function getDirContents($dir, $filter = '', &$results = array()) {
$files = scandir($dir);
foreach($files as $key => $value){
$path = realpath($dir.DIRECTORY_SEPARATOR.$value);
if(!is_dir($path)) {
if(empty($filter) || preg_match($filter, $path)) $results[] = $path;
} elseif($value != "." && $value != "..") {
getDirContents($path, $filter, $results);
}
}
return $results;
}
// Simple Call: List all files
var_dump(getDirContents('/xampp/htdocs/WORK'));
// Regex Call: List php files only
var_dump(getDirContents('/xampp/htdocs/WORK', '/\.php$/'));
Output (example) :
输出(示例):
// Simple Call
array(13) {
[0]=> string(69) "/xampp/htdocs/WORK.htaccess"
[1]=> string(73) "/xampp/htdocs/WORKConverter.php"
[2]=> string(69) "/xampp/htdocs/WORKEvent.php"
[3]=> string(70) "/xampp/htdocs/WORKdefault_filter.json"
[4]=> string(68) "/xampp/htdocs/WORKdefault_filter.xml"
[5]=> string(80) "/xampp/htdocs/WORKCaching/ApcCache.php"
[6]=> string(84) "/xampp/htdocs/WORKCaching/CacheFactory.php"
}
// Regex Call
array(13) {
[0]=> string(69) "/xampp/htdocs/WORKEvent.php"
[1]=> string(73) "/xampp/htdocs/WORKConverter.php"
[2]=> string(80) "/xampp/htdocs/WORKCaching/ApcCache.php"
[3]=> string(84) "/xampp/htdocs/WORKCaching/CacheFactory.php"
}
James Cameron's proposition.
詹姆斯卡梅隆的提议。
回答by bmatovu
This could help if you wish to get directory contents as an array, ignoring hidden files and directories.
如果您希望将目录内容作为数组获取,而忽略隐藏的文件和目录,这可能会有所帮助。
function dir_tree($dir_path)
{
$rdi = new \RecursiveDirectoryIterator($dir_path);
$rii = new \RecursiveIteratorIterator($rdi);
$tree = [];
foreach ($rii as $splFileInfo) {
$file_name = $splFileInfo->getFilename();
// Skip hidden files and directories.
if ($file_name[0] === '.') {
continue;
}
$path = $splFileInfo->isDir() ? array($file_name => array()) : array($file_name);
for ($depth = $rii->getDepth() - 1; $depth >= 0; $depth--) {
$path = array($rii->getSubIterator($depth)->current()->getFilename() => $path);
}
$tree = array_merge_recursive($tree, $path);
}
return $tree;
}
The result would be something like;
结果会是这样的;
dir_tree(__DIR__.'/public');
[
'css' => [
'style.css',
'style.min.css',
],
'js' => [
'script.js',
'script.min.js',
],
'favicon.ico',
]
回答by patriziotomato
My proposal without ugly "foreach" control structures is
我没有丑陋的“foreach”控制结构的建议是
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));
$allFiles = array_filter(iterator_to_array($iterator), function($file) {
return $file->isFile();
});
You may only want to extract the filepath, which you can do so by:
您可能只想提取文件路径,您可以这样做:
array_keys($allFiles);
Still 4 lines of code, but more straight forward than using a loop or something.
仍然是 4 行代码,但比使用循环或其他东西更直接。
回答by majick
Here's a modified version of Hors answer, works slightly better for my case, as it strips out the base directory that is passed as it goes, and has a recursive switch that can be set to false which is also handy. Plus to make the output more readable, I've separated the file and subdirectory files, so the files are added first then the subdirectory files (see result for what I mean.)
这是 Hors 答案的修改版本,对我的情况稍好一些,因为它删除了传递的基本目录,并且具有可以设置为 false 的递归开关,这也很方便。另外,为了使输出更具可读性,我将文件和子目录文件分开,因此先添加文件,然后添加子目录文件(请参阅结果以了解我的意思。)
I tried a few other methods and suggestions around and this is what I ended up with. I had another working method already that was very similar, but seemed to fail where there was a subdirectory with no files but that subdirectory had a subsubdirectory withfiles, it didn't scan the subsubdirectory for files - so some answers may need to be tested for that case.)... anyways thought I'd post my version here too in case someone is looking...
我尝试了其他一些方法和建议,这就是我最终得到的。我已经有另一种非常相似的工作方法,但是在没有文件的子目录但该子目录有一个包含文件的子子目录的情况下似乎失败了,它没有扫描文件的子子目录- 因此可能需要测试一些答案对于那种情况。)...反正我想我也会在这里发布我的版本,以防有人在看...
function get_filelist_as_array($dir, $recursive = true, $basedir = '', $include_dirs = false) {
if ($dir == '') {return array();} else {$results = array(); $subresults = array();}
if (!is_dir($dir)) {$dir = dirname($dir);} // so a files path can be sent
if ($basedir == '') {$basedir = realpath($dir).DIRECTORY_SEPARATOR;}
$files = scandir($dir);
foreach ($files as $key => $value){
if ( ($value != '.') && ($value != '..') ) {
$path = realpath($dir.DIRECTORY_SEPARATOR.$value);
if (is_dir($path)) {
// optionally include directories in file list
if ($include_dirs) {$subresults[] = str_replace($basedir, '', $path);}
// optionally get file list for all subdirectories
if ($recursive) {
$subdirresults = get_filelist_as_array($path, $recursive, $basedir, $include_dirs);
$results = array_merge($results, $subdirresults);
}
} else {
// strip basedir and add to subarray to separate file list
$subresults[] = str_replace($basedir, '', $path);
}
}
}
// merge the subarray to give the list of files then subdirectory files
if (count($subresults) > 0) {$results = array_merge($subresults, $results);}
return $results;
}
I suppose one thing to be careful of it not to pass a $basedir value to this function when calling it... mostly just pass the $dir (or passing a filepath will work now too) and optionally $recursive as false if and as needed. The result:
我想有一件事要小心,在调用它时不要将 $basedir 值传递给这个函数......主要只是传递 $dir (或传递文件路径现在也可以工作)并且可选地 $recursive 为 false if 和 as需要。结果:
[0] => demo-image.png
[1] => filelist.php
[2] => tile.png
[3] => 2015\header.png
[4] => 2015\background.jpg
Enjoy! Okay, back to the program I'm actually using this in...
享受!好的,回到我实际使用的程序......
UPDATEAdded extra argument for including directories in the file list or not (remembering other arguments will need to be passed to use this.) eg.
更新添加了额外的参数以在文件列表中包含目录或不包含目录(记住需要传递其他参数才能使用它。)例如。
$results = get_filelist_as_array($dir, true, '', true);
$results = get_filelist_as_array($dir, true, '', true);
回答by chrinux
This solution did the job for me. The RecursiveIteratorIterator lists all directories and files recursively but unsorted. The program filters the list and sorts it.
这个解决方案为我完成了工作。RecursiveIteratorIterator 以递归方式列出所有目录和文件,但未排序。该程序过滤列表并对其进行排序。
I'm sure there is a way to write this shorter; feel free to improve it. It is just a code snippet. You may want to pimp it to your purposes.
我敢肯定有一种方法可以将其写得更短;随意改进它。它只是一个代码片段。你可能想把它拉到你的目的。
<?php
$path = '/pth/to/your/directories/and/files';
// an unsorted array of dirs & files
$files_dirs = iterator_to_array( new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path),RecursiveIteratorIterator::SELF_FIRST) );
echo '<html><body><pre>';
// create a new associative multi-dimensional array with dirs as keys and their files
$dirs_files = array();
foreach($files_dirs as $dir){
if(is_dir($dir) AND preg_match('/\/\.$/',$dir)){
$d = preg_replace('/\/\.$/','',$dir);
$dirs_files[$d] = array();
foreach($files_dirs as $file){
if(is_file($file) AND $d == dirname($file)){
$f = basename($file);
$dirs_files[$d][] = $f;
}
}
}
}
//print_r($dirs_files);
// sort dirs
ksort($dirs_files);
foreach($dirs_files as $dir => $files){
$c = substr_count($dir,'/');
echo str_pad(' ',$c,' ', STR_PAD_LEFT)."$dir\n";
// sort files
asort($files);
foreach($files as $file){
echo str_pad(' ',$c,' ', STR_PAD_LEFT)."|_$file\n";
}
}
echo '</pre></body></html>';
?>
回答by Koushik Das
Here is what I came up with and this is with not much lines of code
这是我想出的,代码行不多
function show_files($start) {
$contents = scandir($start);
array_splice($contents, 0,2);
echo "<ul>";
foreach ( $contents as $item ) {
if ( is_dir("$start/$item") && (substr($item, 0,1) != '.') ) {
echo "<li>$item</li>";
show_files("$start/$item");
} else {
echo "<li>$item</li>";
}
}
echo "</ul>";
}
show_files('./');
It outputs something like
它输出类似
..idea
.add.php
.add_task.php
.helpers
.countries.php
.mysqli_connect.php
.sort.php
.test.js
.test.php
.view_tasks.php
** The dots are the dots of unoordered list.
** 点是无序列表的点。
Hope this helps.
希望这可以帮助。
回答by Rain
@A-312's solution may cause memory problems as it may create a huge array if /xampp/htdocs/WORK
contains a lot of files and folders.
@A-312 的解决方案可能会导致内存问题,因为如果/xampp/htdocs/WORK
包含大量文件和文件夹,它可能会创建一个巨大的数组。
If you have PHP 7 then you can use Generatorsand optimize PHP's memory like this:
如果你有 PHP 7,那么你可以使用Generators并像这样优化 PHP 的内存:
function getDirContents($dir) {
$files = scandir($dir);
foreach($files as $key => $value){
$path = realpath($dir.DIRECTORY_SEPARATOR.$value);
if(!is_dir($path)) {
yield $path;
} else if($value != "." && $value != "..") {
yield from getDirContents($path);
yield $path;
}
}
}
foreach(getDirContents('/xampp/htdocs/WORK') as $value) {
echo $value."\n";
}