Using a Recursive Function to Traverse a Directory Tree
Part - 2
In this tutorial the original directory listing script will become more user-friendly by
enhancing it in a number of ways:
* A directory path for scanning can be conveniently set through the HTML form.
* All files in a subdirectory displayed first and sub-subdirectories it contains go after the files.
* A few CSS styles are added for a more pleasant view.
<?php
// Define a recursive function:
function list_dir($start) {
static $level = 0; // Represents a level of depth of subdirectories below
// the starting point, used for indenting the listing.
// Get a list of files and directories
// inside the specified path as an array:
$contents = @scandir($start);
// The @ symbol is the error suppression operator that stops
// PHP from generating any errors should a problem occur during
// a scan, cluttering up the screen.
# ---------------------------------- #
# --- ERROR MANAGEMENT DIVISION. --- #
// Report if a problem occurred:
if ($contents === false) {
echo "\n";
echo "<b>Warning:</b> could not open the '$start' directory\n";
echo "The directory permissions are: " . substr(sprintf('%o', fileperms($start)), -4);
echo "\n\n";
// Roll back to the previous level of indentation:
$level--;
// Quit the current invocation of the function:
return;
} // End of IF.
# --- END OF ERROR MANAGEMENT DIVISION. --- #
# ----------------------------------------- #
// Initiate an array to store subdirectories of the current directory:
$subdirs = [];
// Loop over the files and directories:
foreach ($contents as $item) {
# ---------------------- #
# --- DATA DIVISION. --- #
// Quit iterations when the special entries
// . (current directory) and .. (parent directory)
// are encountered:
if ($item === '.' || $item === '..') {
continue; // Without this part the script would
// go into an INFINITE LOOP.
}
// This time, instead of echoing spaces for indentation directly,
// we save them into the '$indentation_str' variable to use later
// in a couple of places.
$indentation_str = '';
// Create indentation, based on the level of depth:
for ($indent = 0; $indent <= $level; $indent++) {
// In this example each indentation will consist of two space characters:
$indentation_str .= ' ';
}
# --- DATA DIVISION. --- #
# ---------------------- #
# ----------------------------- #
# --- PROCEDURE DIVISION 1. --- #
if (!is_dir("$start/$item")) {
// Echo files only:
echo "<span class=\"dir-listing-indentation\">${indentation_str}</span><a href=\"$start/$item\" target=\"_blank\">$item</a>\n";
// Note that most likely you won't be able to follow those links,
// unless your browser is Firefox and you have configured it
// to allow opening local files on your computer.
// This topic is outside of the scope of this tutorial.
} else {
// But save subdirectory paths in an array:
$subdirs[] = "$start/$item";
} // End of IF-ELSE.
# --- END OF PROCEDURE DIVISION 1. --- #
# ------------------------------------ #
} // End of FOREACH loop.
# ----------------------------- #
# --- PROCEDURE DIVISION 2. --- #
// Loop through the array of collected subdirectories:
foreach($subdirs as $subdir) {
// Output the name of a subdirectory:
echo "\n";
echo "${indentation_str} subdirectory: $subdir\n";
// Increment the static variable $level by 1 for indentation purposes:
$level++;
// Call the list_dir() function (from within its own code):
echo list_dir($subdir);
}
// Roll back to the previous level of indentation:
$level--;
# --- END OF PROCEDURE DIVISION 2. --- #
# ------------------------------------ #
} // End of list_dir() function.
/* ----------------------------- */
/* ----------------------------- */
?>
<!-- MAIN HTML CODE -->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Directory Listing</title>
<!-- Add a few CSS rules -->
<style>
.dir-listing-indentation {
background: rgba(200,40,0,.15);
margin-right: .4em;
}
</style>
</head>
<body>
<form action="" method="get">
<label for="dir">Enter directory path</label>
<input type="text" name="dir" id="dir" value="<?php
// Make the input field "sticky":
if (isset($_GET['dir'])) {
echo $_GET['dir'];
}
?>">
<input type="submit">
</form>
<?php
// when the form is submitted, determine a path to the directory
// of interest (the starting-point) and start the listing by
// calling the list_dir() recursive function:
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
if (isset($_GET['dir'])) {
$dir = $_GET['dir'];
echo "<h1>Directory: $dir</h1>\n";
echo "<pre class=\"dir-listing\">";
list_dir($dir);
echo "</pre>";
}
} // End of submission IF.
?>
</body>
</html>
<!-- END OF MAIN HTML CODE -->
This page was last updated on January 28, 2021