Using a Recursive Function to Traverse a Directory Tree
Part - 1
Through the following script I'll show you how to use a function that calls itself to scan a given directory and output its contents diving into its subdirectories. If you're curious about the second part of this tutorial, it's based on the code from this page, but has a few enhancements for a better user experience.
This material is inspired by a snippet of code I've learnt long time ago from a book named 'PHP Advanced and Object-Oriented Programming' by Larry Ullman' that I highly recommend you to read if you'd like to broaden your knowledge in PHP language in general and its more esoteric parts.
<?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.
//
// The variable is set as static so it will remember
// its value from function call to function call.
// It's a very handy feature to have in a recursive function,
// without it we would need to use a global variable.
// 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. --- #
# ----------------------------------------- #
# --------------------------- #
# --- PROCEDURE DIVISION. --- #
// Loop over the files and directories:
foreach ($contents as $item) {
// 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.
}
// 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:
echo ' ';
}
// Output the current item as an html link:
echo "<a href=\"file://$start/$item\"
title=\"Full Path: $start/$item\"
target=\"_blank\"
>$item</a>\n";
// Note that most likely you won't be able to follow these 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.
if (is_dir("$start/$item")) {
// If the current item is a directory, increment the static
// variable $level by 1 for indentation purposes,
// and call the list_dir() function (FROM WITHIN ITS OWN CODE):
$level++;
echo list_dir("$start/$item");
} // End of IF.
} // End of FOREACH loop.
// Roll back to the previous level of indentation:
$level--;
# --- END OF PROCEDURE DIVISION. --- #
# ---------------------------------- #
} // End of list_dir() function.
?>
<!-- MAIN HTML CODE -->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Directory Listing</title>
</head>
<body>
<?php
$dir = '/usr/lib/apt'; A path to the directory of interest (the starting-point).
echo "<h1>Directory: $dir</h1>\n";
echo "<pre>";
list_dir($dir);
echo "</pre>";
?>
</body>
</html>
<!-- END OF MAIN HTML CODE -->
Navigate to the second part of this tutorial to see some ideas on enhancing this script to make it more user-friendly.