Revision: 38297
Updated Code
at June 26, 2012 00:04 by SoN9ne
Updated Code
<?php
/**
* Scans a directory recursively
* Can filter the directory to show only desired file extensions
*
* @author Jeremy Simkins <SoN9ne>
*/
/**
* Prepare filters
* - Do not edit unless you know what you are doing!
* - Look below (Look for BEGIN) to edit the filters
*/
# Define search Filters
$searchFilter = array();
$searchFilter['file'] = array();
$searchFilter['extension'] = array();
$searchFilter['directory'] = array();
# Define ignore Filters
$ignore = array();
$ignore['file'] = array();
$ignore['extension'] = array();
$ignore['directory'] = array();
//--> End Prepare filters
//-----[ BEGIN - Edit this data as you see fit ]-----------------------------------\\
/**
* Directory to scan
* @var string
*/
$directory = "../"; // up one directory to get all the files of the system
/**
* Set the maximum depth for the scan
*
* @var mixed - NULL|int - NULL will have no depth limitation, int is the number of levels deep to step into
*/
define('MAX_SCAN_DEPTH', NULL);
/**
* Custom search filters
* - You can add any type of filter to limit the search.
*
* Notes:
* - Extension and directory filters should be all lowercase
* - File filters should include the extension and are case-sensitive
*/
# Define search extension filters
//$searchFilter['extension'][] = 'php';
# Define search file filters
//$searchFilter['file'][] = '';
# Define search directory filters
//$searchFilter['directory'][] = '';
//--> End search filters
/**
* Edit the ignore filters
*/
# Define ignore extension filters
$ignore['extension'][] = 'buildpath'; // ZDE file
$ignore['extension'][] = 'ds_store'; // Desktop Services Store file
$ignore['extension'][] = 'project'; // ZDE file
# Define ignore file filters
//$ignore['file'][] = '';
# Define ignore directory filters
$ignore['directory'][] = '.svn'; // Do not scan svn directories
$ignore['directory'][] = '.settings'; // Do not scan ZDE .setting folder
$ignore['directory'][] = '__sessions'; // Do not scan custom sessions storage folder
//--> End ignore filters
//-----[ STOP - Edit this data as you see fit ]-----------------------------------\\
/**
* Do Not edit below unless you know what you are doing
*/
# Set timezone
date_default_timezone_set('America/New_York');
# Total files flag
$totalFiles = 0;
$totalDirectories = 0;
# Define direcoty tree array
$directory_tree = array();
# Scan the directory
$directory_tree = customScanDir($directory, $searchFilter, $ignore);
# Sort the array
array_sort($directory_tree, 'name');
//echo '<pre>';
//print_r($directory_tree);
//echo '</pre>';
//die();
# Start output buffering
ob_start();
# Display the content
displayDirRecursively($directory_tree, $totalFiles, $totalDirectories);
# Save output to a var
$tmp = ob_get_contents();
# Delete the output buffer
ob_end_clean();
# Output the page
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Scanner</title>
<style>
body {
margin: 0;
padding: 0;
font: normal 14px Arial;
color: #666;
background: #efefef;
}
ul,ol {
background: #fff;
border: 4px solid #fff;
}
.dirList {
margin: 5px auto;
width: 60%;
overflow: hidden;
-moz-box-shadow: 0 0 20px #b5b5b5;
}
#detail-container {
margin: 5px auto;
width: 60%;
}
#details,#legend {
margin: 5px auto;
-moz-box-shadow: 0 0 20px #b5b5b5;
}
#details {
float: left;
width: 70%;
list-style: none;
}
#legend {
display: inline-block;
float: right;
width: 20%;
}
.clear {
clear: both;
}
li {
line-height: 1.8em;
margin: 0 5px;
padding-left: 2em;
text-indent: -2em;
width: 100%;
}
ol.legend:first-child {
background: maroon;
}
.dirList li:nth-child(even) {
background: #fff;
}
.dirList li:nth-child(odd) {
background: #ecf3fe;
}
.dirList li:hover {
background: yellow;
}
.dirList ul {
margin-left: -30px;
}
#details .title,#legend .title {
list-style: none;
font-weight: bold;
border-bottom: 1px solid #ccc;
margin: 0 0 0 -38px;
}
.folder {
list-style: circle;
}
.file {
list-style: square;
}
h3,h4 {
padding: 10px;
margin: 0px;
font: normal 20px 'Trebuchet MS';
text-align: center;
}
h4 {
font: normal 15px 'Trebuchet MS';
}
a {
color: #0079e0;
}
a:visited {
color: purple;
}
</style>
</head>
<body>
<div id="detail-container">
<ol id="details">
<li class="title">Details:</li>
<li>Total Directories Scanned: <strong><?php echo $totalDirectories; ?></strong></li>
<li>Total Files Located: <strong><?php echo $totalFiles; ?></strong></li>
</ol>
<ol id="legend">
<li class="title">Legend:</li>
<li class="folder">Folder</li>
<li class="file">File</li>
</ol>
<div class="clear"></div>
</div>
<hr />
<?php
# Output the buffer
echo $tmp;
?>
</body>
</html>
<?php
/**
* Recursively scans the directory
*
* @param string $directory - Directory to scan
* @param array $searchFilter - Array of serch data
* @param array $ignore - Array of data to ignore
* @param int $depth - Flag for knowing the depth of the scan
* @throws Exception
*/
function customScanDir($directory = '.', $searchFilter = NULL, $ignore = NULL, $depth = 0) {
if ( MAX_SCAN_DEPTH && $depth > MAX_SCAN_DEPTH ) return array();
if ( substr($directory, -1) == '/' ) {
$directory = substr($directory, 0, -1);
}
try {
try {
$directory_tree = array(); // Define output array
foreach (new DirectoryIterator($directory) as $fileInfo) {
if ( $fileInfo->isDot() ) continue;
$subdirectories = explode('/', $fileInfo->getPathname());
$tmpName = end($subdirectories);
if ( $fileInfo->isDir() && !empty($ignore['directory']) && !in_array($tmpName, $ignore['directory']) ) {
$directory_tree['directory'][] = array('path'=>$fileInfo->getPathname(), 'name'=>$tmpName, 'kind'=>'directory', 'content'=>array_sort(customScanDir($fileInfo->getPathname(), $searchFilter, $ignore, $depth + 1), 'name'));
} else if ( $fileInfo->isFile() ) {
$tmpExtension = strtolower(end(explode('.', $tmpName)));
# Ignored files and extensions
if ( !empty($ignore['extension']) && in_array($tmpExtension, $ignore['extension']) || !empty($ignore['file']) && in_array(strtolower($tmpName), $ignore['file']) || !empty($searchFilter['extension']) && !in_array($tmpExtension, $searchFilter['extension']) ) {
continue;
}
# Add the file to the tree if it is searched or we are displaying the entire directory
if ( empty($searchFilter['file']) || !empty($searchFilter['file']) && in_array(strtolower($tmpName), $searchFilter['file']) ) {
$directory_tree['file'][] = array('name'=>$tmpName, 'extension'=>$tmpExtension, 'path'=>$fileInfo->getPathname(), 'lastModified'=>date('M d Y h:i:s a', $fileInfo->getMTime()), 'kind'=>'file');
}
}
}
unset($tmpName, $tmpExtension); // Free tmp vars
return $directory_tree;
} catch ( UnexpectedValueException $e ) {
throw new Exception(sprintf("Directory [%s/] contained a directory that cannot be stepped into", $directory), E_USER_WARNING);
return array(); // Return an empty array
}
} catch ( Exception $e ) {
die($e->getMessage()); // Show the error
}
}
/**
* Steps throught the directory array and displays
*
* @param array $fileSystem - Array of file system
* @param int $totalFiles - Flag to count the total files found
* @param int $totalDirectories - Flag to count the total directories scanned
* @param int $depth - Flag to know the depth of the display
*/
function displayDirRecursively($fileSystem = array(), & $totalFiles = 0, & $totalDirectories = 0, $depth = 0) {
echo '<ul class="' . (($depth) ? "sub-depth-{$depth}" : 'dirList') . '">';
foreach ($fileSystem as $fsType=>$fsData) {
foreach ($fsData as $item) {
if ( $fsType === 'directory' ) {
++$totalDirectories;
echo '<li class="folder">';
echo $item['name'];
if ( isset($item['content']) && is_array($item['content']) && !empty($item['content']) ) {
displayDirRecursively($item['content'], $totalFiles, $totalDirectories, $depth + 1);
}
$deep = 0;
echo '</li>';
} else if ( $fsType === 'file' ) {
++$totalFiles;
echo '<li class="file">';
echo sprintf('<a href="%s" target="_blank" title="%s">%s</a>', $item['path'], $item['path'], $item['name']);
echo '</li>';
}
}
}
echo '</ul>';
}
/**
* Sorts an array by key
*
* @param array $array
* @param mixed $on - string||int
* @param bool $sortASC - TRUE sort ASC, FALSE sort DESC
* @return array
*/
function array_sort($array, $on, $sortASC = TRUE) {
$new_array = array();
$sortable_array = array();
if ( count($array) > 0 ) {
foreach ($array as $k=>$v) {
if ( is_array($v) ) {
foreach ($v as $k2=>$v2) {
if ( $k2 == $on ) {
$sortable_array[$k] = $v2;
}
}
} else {
$sortable_array[$k] = $v;
}
}
if ( $sortASC ) {
asort($sortable_array);
} else {
arsort($sortable_array);
}
foreach ($sortable_array as $k=>$v) {
$new_array[$k] = $array[$k];
}
}
return $new_array;
}
Revision: 38296
Initial Code
Initial URL
Initial Description
Initial Title
Initial Tags
Initial Language
at December 30, 2010 09:44 by SoN9ne
Initial Code
<?php
/**
* Scans a directory recursively
* Can filter the directory to show only desired file extensions
*
* @author Jeremy Simkins <SoN9ne>
*/
/**
* Prepare filters
* - Do not edit unless you know what you are doing!
* - Look below (Look for BEGIN) to edit the filters
*/
# Define search Filters
$searchFilter = array();
$searchFilter['file'] = array();
$searchFilter['extension'] = array();
$searchFilter['directory'] = array();
# Define ignore Filters
$ignore = array();
$ignore['file'] = array();
$ignore['extension'] = array();
$ignore['directory'] = array();
//--> End Prepare filters
//-----[ BEGIN - Edit this data as you see fit ]-----------------------------------\\
/**
* Directory to scan
* @var string
*/
$directory = "../"; // up one directory to get all the files of the system
/**
* Set the maximum depth for the scan
*
* @var mixed - NULL|int - NULL will have no depth limitation, int is the number of levels deep to step into
*/
define('MAX_SCAN_DEPTH', NULL);
/**
* Custom search filters
* - You can add any type of filter to limit the search.
*
* Notes:
* - Extension and directory filters should be all lowercase
* - File filters should include the extension and are case-sensitive
*/
# Define search extension filters
//$searchFilter['extension'][] = 'php';
# Define search file filters
//$searchFilter['file'][] = '';
# Define search directory filters
//$searchFilter['directory'][] = '';
//--> End search filters
/**
* Edit the ignore filters
*/
# Define ignore extension filters
$ignore['extension'][] = 'buildpath'; // ZDE file
$ignore['extension'][] = 'ds_store'; // Desktop Services Store file
$ignore['extension'][] = 'project'; // ZDE file
# Define ignore file filters
//$ignore['file'][] = '';
# Define ignore directory filters
$ignore['directory'][] = '.svn'; // Do not scan svn directories
$ignore['directory'][] = '.settings'; // Do not scan ZDE .setting folder
$ignore['directory'][] = '__sessions'; // Do not scan custom sessions storage folder
//--> End ignore filters
//-----[ STOP - Edit this data as you see fit ]-----------------------------------\\
/**
* Do Not edit below unless you know what you are doing
*/
# Set timezone
date_default_timezone_set('America/New_York');
# Total files flag
$totalFiles = 0;
$totalDirectories = 0;
# Define direcoty tree array
$directory_tree = array();
# Scan the directory
$directory_tree = customScanDir($directory, $searchFilter, $ignore);
# Sort the array
array_sort($directory_tree, 'name');
//echo '<pre>';
//print_r($directory_tree);
//echo '</pre>';
//die();
# Start output buffering
ob_start();
# Display the content
displayDirRecursively($directory_tree, $totalFiles, $totalDirectories);
# Save output to a var
$tmp = ob_get_contents();
# Delete the output buffer
ob_end_clean();
# Output the page
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Scanner</title>
<style>
body {
margin: 0;
padding: 0;
font: normal 14px Arial;
color: #666;
background: #efefef;
}
ul,ol {
background: #fff;
border: 4px solid #fff;
}
.dirList {
margin: 5px auto;
width: 60%;
overflow: hidden;
-moz-box-shadow: 0 0 20px #b5b5b5;
}
#detail-container {
margin: 5px auto;
width: 60%;
}
#details,#legend {
margin: 5px auto;
-moz-box-shadow: 0 0 20px #b5b5b5;
}
#details {
float: left;
width: 70%;
list-style: none;
}
#legend {
display: inline-block;
float: right;
width: 20%;
}
.clear {
clear: both;
}
li {
line-height: 1.8em;
margin: 0 5px;
padding-left: 2em;
text-indent: -2em;
width: 100%;
}
ol.legend:first-child {
background: maroon;
}
.dirList li:nth-child(even) {
background: #fff;
}
.dirList li:nth-child(odd) {
background: #ecf3fe;
}
.dirList li:hover {
background: yellow;
}
.dirList ul {
margin-left: -30px;
}
#details .title,#legend .title {
list-style: none;
font-weight: bold;
border-bottom: 1px solid #ccc;
margin: 0 0 0 -38px;
}
.folder {
list-style: circle;
}
.file {
list-style: square;
}
h3,h4 {
padding: 10px;
margin: 0px;
font: normal 20px 'Trebuchet MS';
text-align: center;
}
h4 {
font: normal 15px 'Trebuchet MS';
}
a {
color: #0079e0;
}
a:visited {
color: purple;
}
</style>
<!--<script type="text/javascript" src="/gs_sortable.js"></script>-->
<!--<script type="text/javascript">-->
<!---->
<!--var TSort_Data = new Array ('scanner', 's', 'd');-->
<!--tsRegister();-->
<!--// -->
<!--</script>-->
</head>
<body>
<div id="detail-container">
<ol id="details">
<li class="title">Details:</li>
<li>Total Directories Scanned: <strong><?php
echo $totalDirectories;
?></strong></li>
<li>Total Files Located: <strong><?php
echo $totalFiles;
?></strong></li>
</ol>
<ol id="legend">
<li class="title">Legend:</li>
<li class="folder">Folder</li>
<li class="file">File</li>
</ol>
<div class="clear"></div>
</div>
<hr />
<?php
# Output the buffer
echo $tmp;
?>
</body>
</html>
<?php
/**
* Recursively scans the directory
*
* @param string $directory - Directory to scan
* @param array $searchFilter - Array of serch data
* @param array $ignore - Array of data to ignore
* @param int $depth - Flag for knowing the depth of the scan
* @throws Exception
*/
function customScanDir($directory = '.', $searchFilter = NULL, $ignore = NULL, $depth = 0) {
if ( MAX_SCAN_DEPTH && $depth > MAX_SCAN_DEPTH ) return array();
if ( substr($directory, -1) == '/' ) {
$directory = substr($directory, 0, -1);
}
try {
try {
$directory_tree = array(); // Define output array
foreach (new DirectoryIterator($directory) as $fileInfo) {
if ( $fileInfo->isDot() ) continue;
$subdirectories = explode('/', $fileInfo->getPathname());
$tmpName = end($subdirectories);
if ( $fileInfo->isDir() && !empty($ignore['directory']) && !in_array($tmpName, $ignore['directory']) ) {
$directory_tree['directory'][] = array('path'=>$fileInfo->getPathname(), 'name'=>$tmpName, 'kind'=>'directory', 'content'=>array_sort(customScanDir($fileInfo->getPathname(), $searchFilter, $ignore, $depth + 1), 'name'));
} else if ( $fileInfo->isFile() ) {
$tmpExtension = strtolower(end(explode('.', $tmpName)));
# Ignored files and extensions
if ( !empty($ignore['extension']) && in_array($tmpExtension, $ignore['extension']) || !empty($ignore['file']) && in_array(strtolower($tmpName), $ignore['file']) || !empty($searchFilter['extension']) && !in_array($tmpExtension, $searchFilter['extension']) ) {
continue;
}
# Add the file to the tree if it is searched or we are displaying the entire directory
if ( empty($searchFilter['file']) || !empty($searchFilter['file']) && in_array(strtolower($tmpName), $searchFilter['file']) ) {
$directory_tree['file'][] = array('name'=>$tmpName, 'extension'=>$tmpExtension, 'path'=>$fileInfo->getPathname(), 'lastModified'=>date('M d Y h:i:s a', $fileInfo->getMTime()), 'kind'=>'file');
}
}
}
unset($tmpName, $tmpExtension); // Free tmp vars
return $directory_tree;
} catch ( UnexpectedValueException $e ) {
throw new Exception(sprintf("Directory [%s/] contained a directory that cannot be stepped into", $directory), E_USER_WARNING);
return array(); // Return an empty array
}
} catch ( Exception $e ) {
die($e->getMessage()); // Show the error
}
}
/**
* Steps throught the directory array and displays
*
* @param array $fileSystem - Array of file system
* @param int $totalFiles - Flag to count the total files found
* @param int $totalDirectories - Flag to count the total directories scanned
* @param int $depth - Flag to know the depth of the display
*/
function displayDirRecursively($fileSystem = array(), & $totalFiles = 0, & $totalDirectories = 0, $depth = 0) {
echo '<ul class="' . (($depth) ? "sub-depth-{$depth}" : 'dirList') . '">';
foreach ($fileSystem as $fsType=>$fsData) {
foreach ($fsData as $item) {
if ( $fsType === 'directory' ) {
++$totalDirectories;
echo '<li class="folder">';
echo $item['name'];
if ( isset($item['content']) && is_array($item['content']) && !empty($item['content']) ) {
displayDirRecursively($item['content'], $totalFiles, $totalDirectories, $depth + 1);
}
$deep = 0;
echo '</li>';
} else if ( $fsType === 'file' ) {
++$totalFiles;
echo '<li class="file">';
echo sprintf('<a href="%s" target="_blank" title="%s">%s</a>', $item['path'], $item['path'], $item['name']);
echo '</li>';
}
}
}
echo '</ul>';
}
/**
* Sorts an array by key
*
* @param array $array
* @param mixed $on - string||int
* @param bool $sortASC - TRUE sort ASC, FALSE sort DESC
* @return array
*/
function array_sort($array, $on, $sortASC = TRUE) {
$new_array = array();
$sortable_array = array();
if ( count($array) > 0 ) {
foreach ($array as $k=>$v) {
if ( is_array($v) ) {
foreach ($v as $k2=>$v2) {
if ( $k2 == $on ) {
$sortable_array[$k] = $v2;
}
}
} else {
$sortable_array[$k] = $v;
}
}
if ( $sortASC ) {
asort($sortable_array);
} else {
arsort($sortable_array);
}
foreach ($sortable_array as $k=>$v) {
$new_array[$k] = $array[$k];
}
}
return $new_array;
}
Initial URL
Initial Description
There seems to be many scan directory systems but I could not find one that works the way I needed. I added in functionality for a search filter and an ignore list. The search filter and ignore list can ignore by extension, file (case-sensitive file name), and directory. I also added in the ability to have a max depth for the scan. The HTML and CSS that are in the script is to preview in the browser the output. If you scan a directory that is outside the webroot then the links will not be built properly. I did not care to resolve this issue as it was not a problem for me. I tested the script in Strict mode and have no errors, warnings, or notices. Pasting this here for a few friends and the community. If you can improve the script, please let me know as I always enjoy learning new techniques. Thanks, SoN9ne
Initial Title
PHP/HTML/CSS - Script to scan a directoy recursively with filters and/or ingore list
Initial Tags
css, php, html, directory
Initial Language
PHP