Список всех файлов и папок в каталоге с рекурсивной функцией PHP
Я пытаюсь пройти через все файлы в каталоге, и если есть каталог, пройти через все его файлы и так далее, пока нет больше каталогов, чтобы перейти. Каждый обработанный элемент будет добавлен в массив результатов в функции ниже. Это не работает, хотя я не уверен, что я могу сделать / что я сделал неправильно, но браузер работает безумно медленно, когда этот код ниже обрабатывается, любая помощь приветствуется, спасибо!
код:
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'));
13 ответов:
получить все файлы и папки в каталоге, не вызывайте функцию, когда у вас есть
.или...код :
<?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'));выход (пример) :
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)
$rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('path/to/folder')); $files = array(); foreach ($rii as $file) { if ($file->isDir()){ continue; } $files[] = $file->getPathname(); } var_dump($files);это принесет вам все файлы с путями.
это более короткая версия:
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));
получить все файлы фильтр(2-й аргумент) и папки в каталоге, не вызвать функцию, когда у вас есть
.или...код :
<?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$/'));выход (пример) :
// 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" }предложение Джеймса Кэмерона.
мое предложение без уродливых структур управления "foreach" - это
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)); $allFiles = array_filter(iterator_to_array($iterator), function($file) { return $file->isFile(); });вы можете только извлечь путь к файлу, который вы можете сделать так:
array_keys($allFiles);еще 4 строки кода, но более прямо вперед, чем с помощью цикла или что-то в этом роде.
вот модифицированная версия ответа Hors, работает немного лучше для моего случая, поскольку он удаляет базовый каталог, который передается по мере его прохождения, и имеет рекурсивный переключатель, который может быть установлен в false, что также удобно. Кроме того, чтобы сделать вывод более читаемым, я разделил файлы файлов и подкаталогов, поэтому сначала добавляются файлы, а затем файлы подкаталогов (см. Результат Для того, что я имею в виду.)
я попробовал несколько других методов и предложений вокруг, и это то, что я в конечном итоге с. У меня уже был другой метод работы, который был очень похож, но, похоже, не удался, когда был подкаталог без файлов, но этот подкаталог имел подкаталог С файлы, он не сканировал подкаталог для файлов - поэтому некоторые ответы, возможно, потребуется проверить для этого случая.)... в любом случае, я думал, что опубликую свою версию здесь, Если кто-то ищет...
function get_filelist_as_array($dir, $recursive = true, $basedir = '') { 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)) { // do not combine with the next line or.. if ($recursive) { // ..non-recursive list will include subdirs $subdirresults = get_filelist_as_array($path,$recursive,$basedir); $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; }Я полагаю, что нужно быть осторожным, чтобы не передать значение $basedir этой функции, когда вызываю его... в основном просто передайте $dir (или передача пути к файлу будет работать и сейчас) и, возможно, $recursive как false, если и по мере необходимости. Результат:
[0] => demo-image.png [1] => filelist.php [2] => tile.png [3] => 2015\header.png [4] => 2015\background.jpgнаслаждайтесь! Хорошо, вернемся к программе, в которой я на самом деле использую это...
Это решение сделало работу для меня. RecursiveIteratorIterator перечисляет все каталоги и файлы рекурсивно, но несортированные. Программа фильтрует список и сортирует его.
Я уверен, что есть способ, чтобы написать это Короче, не стесняйтесь, чтобы улучшить его. Это просто фрагмент кода. Вы можете использовать его в своих целях.
<?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>'; ?>
вот что я придумал и это не много строк кода
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('./');Он выводит что-то вроде
..idea .add.php .add_task.php .helpers .countries.php .mysqli_connect.php .sort.php .test.js .test.php .view_tasks.php** точки-это точки неупорядоченного списка.
надеюсь, что это помогает.
это выведет полный путь всех файлов в данном каталоге, вы также можете передать другие функции обратного вызова recursiveDir.
function printFunc($path){ echo $path."<br>"; } function recursiveDir($path, $fileFunc, $dirFunc){ $openDir = opendir($path); while (($file = readdir($openDir)) !== false) { $fullFilePath = realpath("$path/$file"); if ($file[0] != ".") { if (is_file($fullFilePath)){ if (is_callable($fileFunc)){ $fileFunc($fullFilePath); } } else { if (is_callable($dirFunc)){ $dirFunc($fullFilePath); } recursiveDir($fullFilePath, $fileFunc, $dirFunc); } } } } recursiveDir($dirToScan, 'printFunc', 'printFunc');
вот мой :
function recScan( $mainDir, $allData = array() ) { // hide files $hidefiles = array( ".", "..", ".htaccess", ".htpasswd", "index.php", "php.ini", "error_log" ) ; //start reading directory $dirContent = scandir( $mainDir ) ; foreach ( $dirContent as $key => $content ) { $path = $mainDir . '/' . $content ; // if is readable / file if ( ! in_array( $content, $hidefiles ) ) { if ( is_file( $path ) && is_readable( $path ) ) { $allData[] = $path ; } // if is readable / directory // Beware ! recursive scan eats ressources ! else if ( is_dir( $path ) && is_readable( $path ) ) { /*recursive*/ $allData = recScan( $path, $allData ) ; } } } return $allData ; }
вот у меня, например,
перечислите все файлы и папки в каталоге csv (file) read with PHP recursive function
<?php /** List all the files and folders in a Directory csv(file) read with PHP recursive function */ 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; } $files = getDirContents('/xampp/htdocs/medifree/lab');//here folder name where your folders and it's csvfile; foreach($files as $file){ $csv_file =$file; $foldername = explode(DIRECTORY_SEPARATOR,$file); //using this get your folder name (explode your path); print_r($foldername); if (($handle = fopen($csv_file, "r")) !== FALSE) { fgetcsv($handle); while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) { $num = count($data); for ($c=0; $c < $num; $c++) { $col[$c] = $data[$c]; } } fclose($handle); } } ?>
я улучшил с помощью одной итерации проверки хороший код Hors Sujet, чтобы избежать включения папок в массив результатов:
function getDirContents($dir, &$results = array()){ $files = scandir($dir); foreach($files as $key => $value){ $path = realpath($dir.DIRECTORY_SEPARATOR.$value); if(is_dir($path) == false) { $results[] = $path; } else if($value != "." && $value != "..") { getDirContents($path, $results); if(is_dir($path) == false) { $results[] = $path; } } } return $results; }
Это небольшая модификация majicks ответ.
Я просто изменил структуру массива, возвращаемого функцией.от:
array() => { [0] => "test/test.txt" }To:
array() => { 'test/test.txt' => "test.txt" }
/** * @param string $dir * @param bool $recursive * @param string $basedir * * @return array */ function getFileListAsArray(string $dir, bool $recursive = true, string $basedir = ''): array { 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)) { // do not combine with the next line or.. if ($recursive) { // ..non-recursive list will include subdirs $subdirresults = self::getFileListAsArray($path, $recursive, $basedir); $results = array_merge($results, $subdirresults); } } else { // strip basedir and add to subarray to separate file list $subresults[str_replace($basedir, '', $path)] = $value; } } } // merge the subarray to give the list of files then subdirectory files if (count($subresults) > 0) { $results = array_merge($subresults, $results); } return $results; }может помочь для тех, кто имеет точно такие же ожидаемые результаты, как я.
Comments