我希望我的脚本递归扫描,
$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)、scandir3依此类推。
如何在不在每个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 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 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)到你想要的深度,并清除所有无聊的隐藏文件(例如'.','..')
现在您所要做的就是使用返回的数组,这是一个完整的树结构,按照您的意愿排列视图中的数据。
事实上,你想做的是一种文件管理器,正如你所知,有很多是免费的、开源的。
我希望这对你有帮助,并祝你圣诞快乐。
上一个函数的变体,使用三元运算符使函数更短,使用splat(或spread)运算符为array_push解包数组。
function getFiles(string $directory): array
{
$files = array_diff(scandir($directory), ['.', '..']);
$allFiles = [];
foreach ($files as $file) {
$fullPath = $directory. DIRECTORY_SEPARATOR .$file;
is_dir($fullPath) ? array_push($allFiles, ...getFiles($fullPath)) : array_push($allFiles, $file);
}
return $allFiles;
}
旧的
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个数组的+运算符(我很少看到使用这种运算符,所以它可能对某些人有用)
尽管这个问题已经过时了。但我的回答可以帮助那些访问这个问题的人。
这会递归地扫描目录和子目录,并将输出存储在全局变量中。
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);
现代方式:
use RecursiveIteratorIterator;
use RecursiveDirectoryIterator;
$path = '/var/www/path/to/your/files/';
foreach ( new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $path, RecursiveDirectoryIterator::SKIP_DOTS ) ) as $file ) {
// TODO: Uncomment to see additional information. Do your manipulations with the files here.
// var_dump( $file->getPathname() ); // Or simple way: echo $file;
// var_dump( $file->isFile() );
// var_dump( $file->isDir() );
// var_dump( $file->getFileInfo() );
// var_dump( $file->getExtension() );
// var_dump( $file->getDepth() );
}
创建一个扫描函数并递归调用它。。。
例如:
<?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>';
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;
}