PHP scandir 递归
PHP scandir recursively
我希望我的脚本递归地扫描,
$files = scandir('/dir');
foreach($files as $file){
if(is_dir($file)){
echo '<li><label class="tree-toggler nav-header"><i class="fa fa-folder-o"></i>'.$file.'</label>';
$subfiles = scandir($rooturl.'/'.$file);
foreach($subfiles as $subfile){
// and so on and on and on
}
echo '<li>';
} else {
echo $file.'<br />';
}
}
我想以一种方式循环它,对于 scandir 找到的每个目录,它在该目录中找到的文件夹上运行另一个 scandir,
所以目录 'A' 包含目录 1/2/3,它现在应该是 scandir(1)、scandir(2)、scandir(3)
依此类推找到的每个目录。
如何在不在每个 foreach 中一遍又一遍地复制粘贴代码的情况下轻松实现这一点?
编辑:由于答案与我已经尝试过的几乎完全相同,我将稍微更新一下问题。
使用这个脚本我需要创建一个树视图列表。使用当前发布的脚本,会发生以下 get 的回显:
/images/dir1/file1.png
/images/dir1/file2.png
/images/dir1/file3.png
/images/anotherfile.php
/data/uploads/avatar.jpg
/data/config.php
index.php
我实际需要的是:
<li><label>images</label>
<ul>
<li><label>dir1</label>
<ul>
<li>file1.png</li>
<li>file2.png</li>
<li>file3.png</li>
</ul>
</li>
<li>anotherfile.php</li>
</ul>
</li>
<li><label>data</label>
<ul>
<li><label>uploads</label>
<ul>
<li>avatar.jpg</li>
</ul>
</li>
<li>config.php</li>
</ul>
</li>
<li>index.php</li>
等等,感谢您已经发布的答案!
您可以通过这种方式递归扫描目录,目标是您的最顶层目录:
function scanDir($target) {
if(is_dir($target)){
$files = glob( $target . '*', GLOB_MARK ); //GLOB_MARK adds a slash to directories returned
foreach( $files as $file )
{
scanDir( $file );
}
}
}
您可以根据需要轻松调整此功能。
例如,如果要使用它来删除目录及其内容,您可以这样做:
function delete_files($target) {
if(is_dir($target)){
$files = glob( $target . '*', GLOB_MARK ); //GLOB_MARK adds a slash to directories returned
foreach( $files as $file )
{
delete_files( $file );
}
rmdir( $target );
} elseif(is_file($target)) {
unlink( $target );
}
你不能按照你现在的方式来做这件事。
以下函数递归获取所有目录,任意深的子目录及其内容:
function assetsMap($source_dir, $directory_depth = 0, $hidden = FALSE)
{
if ($fp = @opendir($source_dir))
{
$filedata = array();
$new_depth = $directory_depth - 1;
$source_dir = rtrim($source_dir, '/').'/';
while (FALSE !== ($file = readdir($fp)))
{
// Remove '.', '..', and hidden files [optional]
if ( ! trim($file, '.') OR ($hidden == FALSE && $file[0] == '.'))
{
continue;
}
if (($directory_depth < 1 OR $new_depth > 0) && @is_dir($source_dir.$file))
{
$filedata[$file] = assetsMap($source_dir.$file.'/', $new_depth, $hidden);
}
else
{
$filedata[] = $file;
}
}
closedir($fp);
return $filedata;
}
echo 'can not open dir';
return FALSE;
}
将您的路径传递给函数:
$path = 'elements/images/';
$filedata = assetsMap($path, $directory_depth = 5, $hidden = FALSE);
$filedata 是一个包含所有已创建目录和子目录及其内容的数组。此功能可让您扫描目录结构 ($directory_depth) 到您想要的深度,并摆脱所有无聊的隐藏文件(例如“.”、“..”)
你现在要做的就是使用返回的数组,即完整的树结构,在你的视图中随意排列数据。
您正在尝试做的实际上是一种文件管理器,如您所知,有很多这样的文件管理器是免费的、开源的。
希望对您有所帮助,祝您圣诞快乐。
创建一个扫描函数并调用它recursively...
例如:
<?php
function scandir_rec($root)
{
echo $root . PHP_EOL;
// When it's a file or not a valid dir name
// Print it out and stop recusion
if (is_file($root) || !is_dir($root)) {
return;
}
// starts the scan
$dirs = scandir($root);
foreach ($dirs as $dir) {
if ($dir == '.' || $dir == '..') {
continue; // skip . and ..
}
$path = $root . '/' . $dir;
scandir_rec($path); // <--- CALL THE FUNCTION ITSELF TO DO THE SAME THING WITH SUB DIRS OR FILES.
}
}
// run it when needed
scandir_rec('./rootDir');
你可以对这个函数做很多变化。例如,打印 'li' 标签而不是 PHP_EOL,以创建树视图。
[编辑]
<?php
function scandir_rec($root)
{
// if root is a file
if (is_file($root)) {
echo '<li>' . basename($root) . '</li>';
return;
}
if (!is_dir($root)) {
return;
}
$dirs = scandir($root);
foreach ($dirs as $dir) {
if ($dir == '.' || $dir == '..') {
continue;
}
$path = $root . '/' . $dir;
if (is_file($path)) {
// if file, create list item tag, and done.
echo '<li>' . $dir . '</li>';
} else if (is_dir($path)) {
// if dir, create list item with sub ul tag
echo '<li>';
echo '<label>' . $dir . '</label>';
echo '<ul>';
scandir_rec($path); // <--- then recursion
echo '</ul>';
echo '</li>';
}
}
}
// init call
$rootDir = 'rootDir';
echo '<ul>';
scandir_rec($rootDir);
echo '</ul>';
虽然这个问题很老了。但是我的回答可以帮助到访问这个问题的人。
这将递归扫描目录和子目录并将输出存储在全局变量中。
global $file_info; // All the file paths will be pushed here
$file_info = array();
/**
*
* @function recursive_scan
* @description Recursively scans a folder and its child folders
* @param $path :: Path of the folder/file
*
* */
function recursive_scan($path){
global $file_info;
$path = rtrim($path, '/');
if(!is_dir($path)) $file_info[] = $path;
else {
$files = scandir($path);
foreach($files as $file) if($file != '.' && $file != '..') recursive_scan($path . '/' . $file);
}
}
recursive_scan('/var/www/html/wp-4.7.2/wp-content/plugins/site-backup');
print_r($file_info);
我知道这是一个老问题,但我写了一个更实用的版本。它不使用全局状态,而是使用纯函数来解决问题:
function scanAllDir($dir) {
$result = [];
foreach(scandir($dir) as $filename) {
if ($filename[0] === '.') continue;
$filePath = $dir . '/' . $filename;
if (is_dir($filePath)) {
foreach (scanAllDir($filePath) as $childFilename) {
$result[] = $filename . '/' . $childFilename;
}
} else {
$result[] = $filename;
}
}
return $result;
}
function getFiles(string $directory, array $allFiles = []): array
{
$files = array_diff(scandir($directory), ['.', '..']);
foreach ($files as $file) {
$fullPath = $directory. DIRECTORY_SEPARATOR .$file;
if( is_dir($fullPath) )
$allFiles += getFiles($fullPath, $allFiles);
else
$allFiles[] = $file;
}
return $allFiles;
}
我知道这是旧的,但我想展示与其他答案略有不同的版本。使用 array_diff 丢弃“.”和“..”文件夹。还有用于组合 2 个数组的 + 运算符(我很少看到它被使用,所以它可能对某些人有用)
function deepScan($dir = __DIR__){
static $allFiles = [];
$allFiles[$dir] = [];
$directories = array_values(array_diff(scandir($dir), ['.', '..']));
foreach($directories as $directory){
if(is_dir("$dir\$directory")){
foreach(deepScan("$dir\$directory") as $key => $value) $allFiles[$key] = $value;
}
else{
$allFiles[$dir][] = "$directory";
}
}
return $allFiles;
}
我希望我的脚本递归地扫描,
$files = scandir('/dir');
foreach($files as $file){
if(is_dir($file)){
echo '<li><label class="tree-toggler nav-header"><i class="fa fa-folder-o"></i>'.$file.'</label>';
$subfiles = scandir($rooturl.'/'.$file);
foreach($subfiles as $subfile){
// and so on and on and on
}
echo '<li>';
} else {
echo $file.'<br />';
}
}
我想以一种方式循环它,对于 scandir 找到的每个目录,它在该目录中找到的文件夹上运行另一个 scandir,
所以目录 'A' 包含目录 1/2/3,它现在应该是 scandir(1)、scandir(2)、scandir(3) 依此类推找到的每个目录。
如何在不在每个 foreach 中一遍又一遍地复制粘贴代码的情况下轻松实现这一点?
编辑:由于答案与我已经尝试过的几乎完全相同,我将稍微更新一下问题。
使用这个脚本我需要创建一个树视图列表。使用当前发布的脚本,会发生以下 get 的回显:
/images/dir1/file1.png
/images/dir1/file2.png
/images/dir1/file3.png
/images/anotherfile.php
/data/uploads/avatar.jpg
/data/config.php
index.php
我实际需要的是:
<li><label>images</label>
<ul>
<li><label>dir1</label>
<ul>
<li>file1.png</li>
<li>file2.png</li>
<li>file3.png</li>
</ul>
</li>
<li>anotherfile.php</li>
</ul>
</li>
<li><label>data</label>
<ul>
<li><label>uploads</label>
<ul>
<li>avatar.jpg</li>
</ul>
</li>
<li>config.php</li>
</ul>
</li>
<li>index.php</li>
等等,感谢您已经发布的答案!
您可以通过这种方式递归扫描目录,目标是您的最顶层目录:
function scanDir($target) {
if(is_dir($target)){
$files = glob( $target . '*', GLOB_MARK ); //GLOB_MARK adds a slash to directories returned
foreach( $files as $file )
{
scanDir( $file );
}
}
}
您可以根据需要轻松调整此功能。 例如,如果要使用它来删除目录及其内容,您可以这样做:
function delete_files($target) {
if(is_dir($target)){
$files = glob( $target . '*', GLOB_MARK ); //GLOB_MARK adds a slash to directories returned
foreach( $files as $file )
{
delete_files( $file );
}
rmdir( $target );
} elseif(is_file($target)) {
unlink( $target );
}
你不能按照你现在的方式来做这件事。 以下函数递归获取所有目录,任意深的子目录及其内容:
function assetsMap($source_dir, $directory_depth = 0, $hidden = FALSE)
{
if ($fp = @opendir($source_dir))
{
$filedata = array();
$new_depth = $directory_depth - 1;
$source_dir = rtrim($source_dir, '/').'/';
while (FALSE !== ($file = readdir($fp)))
{
// Remove '.', '..', and hidden files [optional]
if ( ! trim($file, '.') OR ($hidden == FALSE && $file[0] == '.'))
{
continue;
}
if (($directory_depth < 1 OR $new_depth > 0) && @is_dir($source_dir.$file))
{
$filedata[$file] = assetsMap($source_dir.$file.'/', $new_depth, $hidden);
}
else
{
$filedata[] = $file;
}
}
closedir($fp);
return $filedata;
}
echo 'can not open dir';
return FALSE;
}
将您的路径传递给函数:
$path = 'elements/images/';
$filedata = assetsMap($path, $directory_depth = 5, $hidden = FALSE);
$filedata 是一个包含所有已创建目录和子目录及其内容的数组。此功能可让您扫描目录结构 ($directory_depth) 到您想要的深度,并摆脱所有无聊的隐藏文件(例如“.”、“..”)
你现在要做的就是使用返回的数组,即完整的树结构,在你的视图中随意排列数据。
您正在尝试做的实际上是一种文件管理器,如您所知,有很多这样的文件管理器是免费的、开源的。
希望对您有所帮助,祝您圣诞快乐。
创建一个扫描函数并调用它recursively...
例如:
<?php
function scandir_rec($root)
{
echo $root . PHP_EOL;
// When it's a file or not a valid dir name
// Print it out and stop recusion
if (is_file($root) || !is_dir($root)) {
return;
}
// starts the scan
$dirs = scandir($root);
foreach ($dirs as $dir) {
if ($dir == '.' || $dir == '..') {
continue; // skip . and ..
}
$path = $root . '/' . $dir;
scandir_rec($path); // <--- CALL THE FUNCTION ITSELF TO DO THE SAME THING WITH SUB DIRS OR FILES.
}
}
// run it when needed
scandir_rec('./rootDir');
你可以对这个函数做很多变化。例如,打印 'li' 标签而不是 PHP_EOL,以创建树视图。
[编辑]
<?php
function scandir_rec($root)
{
// if root is a file
if (is_file($root)) {
echo '<li>' . basename($root) . '</li>';
return;
}
if (!is_dir($root)) {
return;
}
$dirs = scandir($root);
foreach ($dirs as $dir) {
if ($dir == '.' || $dir == '..') {
continue;
}
$path = $root . '/' . $dir;
if (is_file($path)) {
// if file, create list item tag, and done.
echo '<li>' . $dir . '</li>';
} else if (is_dir($path)) {
// if dir, create list item with sub ul tag
echo '<li>';
echo '<label>' . $dir . '</label>';
echo '<ul>';
scandir_rec($path); // <--- then recursion
echo '</ul>';
echo '</li>';
}
}
}
// init call
$rootDir = 'rootDir';
echo '<ul>';
scandir_rec($rootDir);
echo '</ul>';
虽然这个问题很老了。但是我的回答可以帮助到访问这个问题的人。
这将递归扫描目录和子目录并将输出存储在全局变量中。
global $file_info; // All the file paths will be pushed here
$file_info = array();
/**
*
* @function recursive_scan
* @description Recursively scans a folder and its child folders
* @param $path :: Path of the folder/file
*
* */
function recursive_scan($path){
global $file_info;
$path = rtrim($path, '/');
if(!is_dir($path)) $file_info[] = $path;
else {
$files = scandir($path);
foreach($files as $file) if($file != '.' && $file != '..') recursive_scan($path . '/' . $file);
}
}
recursive_scan('/var/www/html/wp-4.7.2/wp-content/plugins/site-backup');
print_r($file_info);
我知道这是一个老问题,但我写了一个更实用的版本。它不使用全局状态,而是使用纯函数来解决问题:
function scanAllDir($dir) {
$result = [];
foreach(scandir($dir) as $filename) {
if ($filename[0] === '.') continue;
$filePath = $dir . '/' . $filename;
if (is_dir($filePath)) {
foreach (scanAllDir($filePath) as $childFilename) {
$result[] = $filename . '/' . $childFilename;
}
} else {
$result[] = $filename;
}
}
return $result;
}
function getFiles(string $directory, array $allFiles = []): array
{
$files = array_diff(scandir($directory), ['.', '..']);
foreach ($files as $file) {
$fullPath = $directory. DIRECTORY_SEPARATOR .$file;
if( is_dir($fullPath) )
$allFiles += getFiles($fullPath, $allFiles);
else
$allFiles[] = $file;
}
return $allFiles;
}
我知道这是旧的,但我想展示与其他答案略有不同的版本。使用 array_diff 丢弃“.”和“..”文件夹。还有用于组合 2 个数组的 + 运算符(我很少看到它被使用,所以它可能对某些人有用)
function deepScan($dir = __DIR__){
static $allFiles = [];
$allFiles[$dir] = [];
$directories = array_values(array_diff(scandir($dir), ['.', '..']));
foreach($directories as $directory){
if(is_dir("$dir\$directory")){
foreach(deepScan("$dir\$directory") as $key => $value) $allFiles[$key] = $value;
}
else{
$allFiles[$dir][] = "$directory";
}
}
return $allFiles;
}