Listing all the folders subfolders and files in a directory using php
Please give me a solution for listing all the folders,subfolders,开发者_Go百科files in a directory using php. My folder structure is like this:
Main Dir
Dir1
SubDir1
File1
File2
SubDir2
File3
File4
Dir2
SubDir3
File5
File6
SubDir4
File7
File8
I want to get the list of all the files inside each folder.
Is there any shell script command in php?
function listFolderFiles($dir){
$ffs = scandir($dir);
unset($ffs[array_search('.', $ffs, true)]);
unset($ffs[array_search('..', $ffs, true)]);
// prevent empty ordered elements
if (count($ffs) < 1)
return;
echo '<ol>';
foreach($ffs as $ff){
echo '<li>'.$ff;
if(is_dir($dir.'/'.$ff)) listFolderFiles($dir.'/'.$ff);
echo '</li>';
}
echo '</ol>';
}
listFolderFiles('Main Dir');
A very simple way to show folder structure makes use of RecursiveTreeIterator
class (PHP 5 >= 5.3.0, PHP 7) and generates an ASCII graphic tree.
$it = new RecursiveTreeIterator(new RecursiveDirectoryIterator("/path/to/dir", RecursiveDirectoryIterator::SKIP_DOTS));
foreach($it as $path) {
echo $path."<br>";
}
http://php.net/manual/en/class.recursivetreeiterator.php
There is also some control over the ASCII representation of the tree by changing the prefixes using RecursiveTreeIterator::setPrefixPart
, for example $it->setPrefixPart(RecursiveTreeIterator::PREFIX_LEFT, "|");
This code lists all directories and files in sorted order in a tree view. It's a site map generator with hyper-links to all the site resources. The full web page source is here. You'll need to change the path on the ninth line from the end.
<?php
$pathLen = 0;
function prePad($level)
{
$ss = "";
for ($ii = 0; $ii < $level; $ii++)
{
$ss = $ss . "| ";
}
return $ss;
}
function myScanDir($dir, $level, $rootLen)
{
global $pathLen;
if ($handle = opendir($dir)) {
$allFiles = array();
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
if (is_dir($dir . "/" . $entry))
{
$allFiles[] = "D: " . $dir . "/" . $entry;
}
else
{
$allFiles[] = "F: " . $dir . "/" . $entry;
}
}
}
closedir($handle);
natsort($allFiles);
foreach($allFiles as $value)
{
$displayName = substr($value, $rootLen + 4);
$fileName = substr($value, 3);
$linkName = str_replace(" ", "%20", substr($value, $pathLen + 3));
if (is_dir($fileName)) {
echo prePad($level) . $linkName . "<br>\n";
myScanDir($fileName, $level + 1, strlen($fileName));
} else {
echo prePad($level) . "<a href=\"" . $linkName . "\" style=\"text-decoration:none;\">" . $displayName . "</a><br>\n";
}
}
}
}
?><!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Site Map</title>
</head>
<body>
<h1>Site Map</h1>
<p style="font-family:'Courier New', Courier, monospace; font-size:small;">
<?php
$root = '/home/someuser/www/website.com/public';
$pathLen = strlen($root);
myScanDir($root, 0, strlen($root)); ?>
</p>
</body>
</html>
In case you want to use directoryIterator
Following function is a re-implementation of @Shef answer with directoryIterator
function listFolderFiles($dir)
{
echo '<ol>';
foreach (new DirectoryIterator($dir) as $fileInfo) {
if (!$fileInfo->isDot()) {
echo '<li>' . $fileInfo->getFilename();
if ($fileInfo->isDir()) {
listFolderFiles($fileInfo->getPathname());
}
echo '</li>';
}
}
echo '</ol>';
}
listFolderFiles('Main Dir');
I'm really fond of SPL Library, they offer iterator's, including RecursiveDirectoryIterator.
If you're looking for a recursive directory listing solutions and arrange them in a multidimensional array. Use below code:
<?php
/**
* Function for recursive directory file list search as an array.
*
* @param mixed $dir Main Directory Path.
*
* @return array
*/
function listFolderFiles($dir)
{
$fileInfo = scandir($dir);
$allFileLists = [];
foreach ($fileInfo as $folder) {
if ($folder !== '.' && $folder !== '..') {
if (is_dir($dir . DIRECTORY_SEPARATOR . $folder) === true) {
$allFileLists[$folder] = listFolderFiles($dir . DIRECTORY_SEPARATOR . $folder);
} else {
$allFileLists[$folder] = $folder;
}
}
}
return $allFileLists;
}//end listFolderFiles()
$dir = listFolderFiles('your searching directory path ex:-F:\xampp\htdocs\abc');
echo '<pre>';
print_r($dir);
echo '</pre>'
?>
Have a look at glob() or the recursive directory iterator.
scandir()
http://php.net/manual/en/function.scandir.php
It will use to make menu bar in directory format
$pathLen = 0;
function prePad($level)
{
$ss = "";
for ($ii = 0; $ii < $level; $ii++)
{
$ss = $ss . "| ";
}
return $ss;
}
function myScanDir($dir, $level, $rootLen)
{
global $pathLen;
if ($handle = opendir($dir)) {
$allFiles = array();
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
if (is_dir($dir . "/" . $entry))
{
$allFiles[] = "D: " . $dir . "/" . $entry;
}
else
{
$allFiles[] = "F: " . $dir . "/" . $entry;
}
}
}
closedir($handle);
natsort($allFiles);
foreach($allFiles as $value)
{
$displayName = substr($value, $rootLen + 4);
$fileName = substr($value, 3);
$linkName = str_replace(" ", " ", substr($value, $pathLen + 3));
if (is_dir($fileName))
{
echo "<li ><a class='dropdown'><span>" . $displayName . " </span></a><ul>";
myScanDir($fileName, $level + 1, strlen($fileName));
echo "</ul></li>";
}
else {
$newstring = substr($displayName, -3);
if($newstring == "PDF" || $newstring == "pdf" )
echo "<li ><a href=\"" . $linkName . "\" style=\"text-decoration:none;\">" . $displayName . "</a></li>";
}
$t;
if($level != 0)
{
if($level < $t)
{
$r = int($t) - int($level);
for($i=0;$i<$r;$i++)
{
echo "</ul></li>";
}
}
}
$t = $level;
}
}
}
?>
<li style="color: #ffffff">
<?php
// ListFolder('D:\PDF');
$root = 'D:\PDF';
$pathLen = strlen($root);
myScanDir($root, 0, strlen($root));
?>
</li>
The precedents answers didn't meet my needs.
If you want all files and dirs in one flat array, you can use this function (found here) :
// Does not support flag GLOB_BRACE
function glob_recursive($pattern, $flags = 0) {
$files = glob($pattern, $flags);
foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) {
$files = array_merge($files, glob_recursive($dir.'/'.basename($pattern), $flags));
}
return $files;
}
In my case :
$paths = glob_recursive(os_path_join($base_path, $current_directory, "*"));
returns me an array like this :
[
'/home/dir',
'/home/dir/image.png',
'/home/dir/subdir',
'/home/dir/subdir/file.php',
]
You can also use dynamic path generation :
$paths = glob_recursive(os_path_join($base_path, $directory, "*"));
With this function :
function os_path_join(...$parts) {
return preg_replace('#'.DIRECTORY_SEPARATOR.'+#', DIRECTORY_SEPARATOR, implode(DIRECTORY_SEPARATOR, array_filter($parts)));
}
If you wan get only directories you can use :
$paths = glob_recursive(os_path_join($base_path, $current_directory, "*"));
$subdirs = array_filter($paths, function($path) {
return is_dir($path);
});
I was looking for a similar function to this. I needed directories as keys and subdirectories as arrays and files to just be placed as values.
I used the following code:
/**
* Return an array of files found within a specified directory.
* @param string $dir A valid directory. If a path, with a file at the end,
* is passed, then the file is trimmed from the directory.
* @param string $regex Optional. If passed, all file names will be checked
* against the expression, and only those that match will
* be returned.
* A RegEx can be just a string, where a '/' will be
* prefixed and a '/i' will be suffixed. Alternatively,
* a string could be a valid RegEx string.
* @return array An array of all files from that directory. If regex is
* set, then this will be an array of any matching files.
*/
function get_files_in_dir(string $dir, $regex = null)
{
$dir = is_dir($dir) ? $dir : dirname($dir);
// A RegEx to check whether a RegEx is a valid RegEx :D
$pass = preg_match("/^([^\\\\a-z ]).+([^\\\\a-z ])[a-z]*$/i", $regex, $matches);
// Any non-regex string will be caught here.
if (isset($regex) && !$pass) {
//$regex = '/'.addslashes($regex).'/i';
$regex = "/$regex/i";
}
// A valid regex delimiter with different delimiters will be caught here.
if (!empty($matches) && $matches[1] !== $matches[2]) {
$regex .= $matches[1] . 'i'; // Append first delimiter and i flag
}
try {
$files = scandir($dir);
} catch (Exception $ex) {
$files = ['.', '..'];
}
$files = array_slice($files, 2); // Remove '.' and '..'
$files = array_reduce($files, function($carry, $item) use ($regex) {
if ((!empty($regex) && preg_match($regex, $item)) || empty($regex)) {
array_push($carry, $item);
}
return $carry;
}, []);
return $files;
}
function str_finish($value, $cap)
{
$quoted = preg_quote($cap, '/');
return preg_replace('/(?:'.$quoted.')+$/u', '', $value).$cap;
}
function get_directory_tree($dir)
{
$fs = get_files_in_dir($dir);
$files = array();
foreach ($fs as $k => $f) {
if (is_dir(str_finish($dir, '/').$f)) {
$fs[$f] = get_directory_tree(str_finish($dir, '/').$f);
} else {
$files[] = $f;
}
unset($fs[$k]);
}
$fs = array_merge($fs, $files);
return $fs;
}
There's a lot to take in.
The first function get_files_in_dir
function was created so that I could get all files and folders in a directory based on a regular expression. I use it here because it has some error checking to make sure a directory is converted into an array.
Next, we have a simple function that just adds a forward slash to the end of a string if there isn't one there already.
Finally, we have the get_directory_tree
function which will iterate through all the folders and sub folders and create an associative array where the folder names are the keys and files are the values (unless the folder has sub folders).
Here is A simple function with scandir
& array_filter
that do the job. filter
needed files using regex. I removed .
..
and hidden files like .htaccess
, you can also customise output using <ul>
and colors and also customise errors in case no scan or empty dirs!.
function getAllContentOfLocation($loc)
{
$scandir = scandir($loc);
$scandir = array_filter($scandir, function($element){
return !preg_match('/^\./', $element);
});
if(empty($scandir)) echo '<li style="color:red">Empty Dir</li>';
foreach($scandir as $file){
$baseLink = $loc . DIRECTORY_SEPARATOR . $file;
echo '<ol>';
if(is_dir($baseLink))
{
echo '<li style="font-weight:bold;color:blue">'.$file.'</li>';
getAllContentOfLocation($baseLink);
}else{
echo '<li>'.$file.'</li>';
}
echo '</ol>';
}
}
//Call function and set location that you want to scan
getAllContentOfLocation('../app');
This is my handy method PHP 7 style:
/**
* @param string $directory
*
* @return SplFileInfo[]
*/
private function getAllFiles(string $directory = './'): array
{
$result = [];
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory), RecursiveIteratorIterator::SELF_FIRST );
/** @var $fileInfo SplFileInfo */
foreach ($iterator as $fileInfo ) {
if ($fileInfo->isFile()) {
$result[] = $fileInfo;
}
}
return $result;
}
Here's another recursive scandir()
as a generator. The generator yields full paths (in the form "basedir/subdirs.../file"
) so it is less suitable for a tree display and more appropriate for directory scanning where you want to do something else with the file paths - such as display an image gallery.
function listFolderFiles($dir){
foreach(scandir($dir) as $file){
if ($file[0] == '.')
continue;
if (is_dir("$dir/$file"))
foreach (listFolderFiles("$dir/$file") as $infile)
yield $infile;
else
yield "${dir}/${file}";
}
}
This implementation skips the directory pointers by skipping all UNIX hidden files (files that start with a period) - if you want to get "hidden" files, then you need to change the directory pointer skipping method to something else.
You can use it like this:
<?php foreach (listFolderFiles('.') as $file) {
?>
<?php echo $file?><br/>
<?php
}?>
You can also try this:
<?php
function listdirs($dir) {
static $alldirs = array();
$dirs = glob($dir . '/*', GLOB_ONLYDIR);
if (count($dirs) > 0) {
foreach ($dirs as $d) $alldirs[] = $d;
}
foreach ($dirs as $dir) listdirs($dir);
return $alldirs;
}
$directory_list = listdirs('xampp');
print_r($directory_list);
?>
define ('PATH', $_SERVER['DOCUMENT_ROOT'] . dirname($_SERVER['PHP_SELF']));
$dir = new DirectoryIterator(PATH);
echo '<ul>';
foreach ($dir as $fileinfo)
{
if (!$fileinfo->isDot()) {
echo '<li><a href="'.$fileinfo->getFilename().'" target="_blank">'.$fileinfo->getFilename().'</a></li>';
echo '</li>';
}
}
echo '</ul>';
Late to the show, but to build off of the accepted answer...
If you want to have all the files and directories in as array (that can be prettied-up nicely with JSON.stringify in javascript), you can modify the function to:
function listFolderFiles($dir) {
$arr = array();
$ffs = scandir($dir);
foreach($ffs as $ff) {
if($ff != '.' && $ff != '..') {
$arr[$ff] = array();
if(is_dir($dir.'/'.$ff)) {
$arr[$ff] = listFolderFiles($dir.'/'.$ff);
}
}
}
return $arr;
}
For the Newbies...
To use the aforementioned JSON.stringify
, your JS/jQuery would be something like:
var ajax = $.ajax({
method: 'POST',
data: {list_dirs: true}
}).done(function(msg) {
$('pre').html(
'FILE LAYOUT<br/>' +
JSON.stringify(JSON.parse(msg), null, 4)
);
});
^ This is assuming you have a <pre>
element in your HTML somewhere. Any flavour of AJAX will do, but I figure most people are using something similar to the jQuery above.
And the accompanying PHP:
if(isset($_POST['list_dirs'])) {
echo json_encode(listFolderFiles($rootPath));
exit();
}
where you already have listFolderFiles
from before.
In my case, I've set my $rootPath
to the root directory of the site...
$rootPath;
if(!isset($rootPath)) {
$rootPath = $_SERVER['DOCUMENT_ROOT'];
}
The end result is something like...
| some_file_1487.smthng []
| some_file_8752.smthng []
| CSS
| | some_file_3615.smthng []
| | some_file_8151.smthng []
| | some_file_7571.smthng []
| | some_file_5641.smthng []
| | some_file_7305.smthng []
| | some_file_9527.smthng []
|
| IMAGES
| | some_file_4515.smthng []
| | some_file_1335.smthng []
| | some_file_1819.smthng []
| | some_file_9188.smthng []
| | some_file_4760.smthng []
| | some_file_7347.smthng []
|
| JSScripts
| | some_file_6449.smthng []
| | some_file_7864.smthng []
| | some_file_3899.smthng []
| | google-code-prettify
| | | some_file_2090.smthng []
| | | some_file_5169.smthng []
| | | some_file_3426.smthng []
| | | some_file_8208.smthng []
| | | some_file_7581.smthng []
| | | some_file_4618.smthng []
| |
| | some_file_3883.smthng []
| | some_file_3713.smthng []
... and so on...
Note: Yours will not look exactly like this - I've modified JSON.stringify
to display tabs (vertical pipes), align all keyed values, remove quotes off of keys, and a couple other things. I will modify this answer with a link if I ever get to uploading it, or get enough interest.
function GetDir($dir) {
if (is_dir($dir)) {
if ($kami = opendir($dir)) {
while ($file = readdir($kami)) {
if ($file != '.' && $file != '..') {
if (is_dir($dir . $file)) {
echo $dir . $file;
// since it is a directory we recurse it.
GetDir($dir . $file . '/');
} else {
echo $dir . $file;
}
}
}
}
closedir($kami);
}
}
This post is for Shef(the one who posted the correct answer). It's the only way I can think of showing him how much I appreciate his code and what I have done with it.
<!DOCTYPE html>
<head><title>Displays Folder Contents</title></head>
<?php
function frmtFolder($Entity){
echo '<li style="font-weight:bold;color:black;list-style-type:none">' . $Entity;
}
function frmtFile($dEntry, $fEntry){
echo '<li style="list-style-type:square">' . '<a href="' . $dEntry . '/' . $fEntry .
'"> ' . $fEntry . ' </a>';
}
function listFolderFiles($dir) {
$ffs = scandir($dir);
unset($ffs[array_search('.', $ffs, true)]);
unset($ffs[array_search('..', $ffs, true)]);
unset($ffs[array_search('index.html', $ffs, true)]);
// prevent empty ordered elements
if (count($ffs) < 1) {return;}
echo '<ul>';
foreach ($ffs as $ff) {
if (is_dir($dir . '/' . $ff)) {
frmtFolder($dir);
} else {
frmtFile($dir, $ff);
}
if (is_dir($dir . '/' . $ff)) {
listFolderFiles($dir . '/' . $ff);
}
echo '</li>';
}
echo '</ul>';
}
listFolderFiles('Folder_To_List_Here');
I plan on expanding the frmtFile to use audio and videos tags in the future.
https://3v4l.org/VsQLb Example Here
function listdirs($dir) {
static $alldirs = array();
$dirs = glob($dir . '/*', GLOB_ONLYDIR);
if (count($dirs) > 0) {
foreach ($dirs as $d) $alldirs[] = $d;
}
foreach ($dirs as $dir) listdirs($dir);
return $alldirs;
}
精彩评论