-
-
Save vrkansagara/ee6b86d488cc5d4ff2f499e1c6f24b4c to your computer and use it in GitHub Desktop.
'tree' console command, in PHP.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/php | |
<?php | |
/** | |
* Because you want "tree", but cannot find the source code quick enough | |
* on the web to compile for OS.X or there is no suitable implementation | |
* on windows. | |
*/ | |
// set error reporting | |
error_reporting(E_STRICT | E_ALL); | |
// handle command line arguments | |
$arg_count = $_SERVER['argc']; | |
if ($arg_count > 1 && $_SERVER['argv'][$arg_count-1]{0} != '-') { | |
$path = $_SERVER['argv'][$arg_count-1]; | |
} else { | |
$path = getcwd(); | |
} | |
$options = getopt('e::', array('exclude::')); | |
if (isset($path) && file_exists($path)) { | |
$path = realpath($path); | |
} else { | |
die('Could not find path: ' . $path . PHP_EOL); | |
} | |
// create the tree's RecursiveDirectoryIterator (and tree iterator) | |
$recursiveIterator = $treeIterator = new Tree_RecursiveDirectoryIterator($path); | |
// if we need to exclude anything, set the RDI to a Filter Iterator | |
// using the TreeIterator as the source to iterate | |
if (isset($options['exclude']) || isset($options['e'])) { | |
Tree_RecursiveFilterIterator::$pattern = (isset($options['e'])) ? $options['e'] : $options['exclude']; | |
$recursiveIterator = new Tree_RecursiveFilterIterator($treeIterator); | |
} | |
// pass the target iterator to a iteratoriterator | |
foreach (new Tree_RecursiveIteratorIterator($recursiveIterator) as $item) { | |
echo $item . PHP_EOL; | |
} | |
/** | |
* Class to handle the iteration of the filesystem | |
*/ | |
class Tree_RecursiveDirectoryIterator extends RecursiveDirectoryIterator | |
{ | |
public function current() | |
{ | |
return $this->getFilename(); | |
} | |
} | |
/** | |
* Class to handle the filtering of items inside a RecrusiveIterator | |
*/ | |
class Tree_RecursiveFilterIterator extends RecursiveFilterIterator | |
{ | |
public static $pattern = null; | |
public function accept() | |
{ | |
$regex = '#^' . self::$pattern . '#'; | |
if ($this->isDir() && preg_match($regex, $this->current() . DIRECTORY_SEPARATOR)) { | |
return false; | |
} | |
return true; | |
} | |
} | |
/** | |
* Class to handle the actual iteration of the nodes. | |
*/ | |
class Tree_RecursiveIteratorIterator extends RecursiveIteratorIterator | |
{ | |
function __construct($treeRecursiveIterator) | |
{ | |
parent::__construct( | |
new RecursiveCachingIterator( | |
$treeRecursiveIterator, | |
CachingIterator::CALL_TOSTRING|CachingIterator::CATCH_GET_CHILD | |
), | |
parent::SELF_FIRST | |
); | |
} | |
function current() | |
{ | |
$tree = ''; | |
for ($l=0; $l < $this->getDepth(); $l++) { | |
$tree .= $this->getSubIterator($l)->hasNext() ? '| ' : ' '; | |
} | |
return $tree | |
. ($this->getSubIterator($l)->hasNext() ? '|- ' : '`- ') | |
. $this->getSubIterator($l)->__toString(); | |
} | |
function __call($func, $params) | |
{ | |
return call_user_func_array(array($this->getSubIterator(), $func), $params); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment