Was es kann
Im Grunde ist es eine Tiefenverzeichniswechsel mit regulärem Ausdruck. Hier ein paar Beispiele:
/etc$ c site enab
/etc/apache2/sites-enabled$ c site ava
/etc/apache2/sites-available$ c php5
/etc/php5/$
Wie ihr an Zeile 2+3 seht, ist aber auch ein Wechsel in höhere Ebenen möglich, wenn nichts in der Tiefe gefunden wurde. Wobei der Wechsel aufwärts auf angegebene Verzeichnisse beschränkt ist, damit das Script nicht irgendwann in / landet.
Diese "Roots" (die Verzeichnisse, in denen auch aufwärts gesucht wird) sind über Parameter änderbar.
Daüberhinaus sollten alle Features von cd zur Verfügung stehen, auch die Autovervollständigung.
Ausprobieren
Zuerst muss php5-cli installiert werden.
sudo apt-get install php5-cli
Kopiert dann das folgende Script "cds" in ~/bin.
Macht cds ausführbar:
chmod +x ~/bin/cds
Diese "Roots" (die Verzeichnisse, in denen auch aufwärts gesucht wird) sind über Parameter änderbar.
Daüberhinaus sollten alle Features von cd zur Verfügung stehen, auch die Autovervollständigung.
Ausprobieren
Zuerst muss php5-cli installiert werden.
sudo apt-get install php5-cli
Kopiert dann das folgende Script "cds" in ~/bin.
#!/usr/bin/php
define('DEBUG', false);
/*
--------------------- Installation
Execute the following command on the bash:
c() { cd "`~/bin/cds $@`"; }; complete -o filenames -o nospace -F _cd c
caution: if you have a symlink in one of your root folders you can jump into the symlink folder but not return
--------------------- Changelog
0.9
"/var/www/project/folder1$ c www" changes now to "/var/www" instead of staying in the same dir
"/var/www/yoho/nextyoho$ c yoho changes now to "/var/www/yoho" instead of staying in the same dir
--------------------- Known Bugs
*/
// define __DIR__ before PHP 5.3
if(!defined('__DIR__')) { define("__DIR__", dirname(__FILE__)); }
// init file error handler
set_error_handler('errorhandler');
// get arguments
$args = array_slice($argv, 1);
// get current working dir
$cwd = exec('pwd');
$home = $_SERVER['HOME'];
dump($cwd, 'CWD: ');
// ---------------------------- imitate cd
// because it is also a replacement for cd imitate its behaviour
// first try cd
if (count($args) === 0) $args = array($home);
exec('cd ' . implode(' ', $args) . ' 2>/dev/null', $output, $return_var);
if ($return_var == 0) { if (isset($args[0])) stdout($args[0]); die(); }
// ---------------------------- handle options
/*
-a : add current directory as root
-r : remove current directory as root
-l : list all roots
*/
$options = getopt('alr:');
// get roots
$conf = __DIR__ . '/cds.conf';
if (!is_file($conf)) touch($conf);
$roots = array_map('trim', file($conf));
// add new root
if (isset($options['a']))
{
// we do not want duplicates
$roots[] = $cwd;
$roots = array_unique($roots);
file_put_contents($conf, implode("\n", $roots));
stderr('Added new root: ' . $cwd);
die($cwd);
}
// list all roots
elseif (isset($options['l']))
{
foreach ($roots as $i=>$root)
{
stderr('['.($i+1).'] '.$root);
}
die($cwd);
}
// remove root
elseif (isset($options['r']))
{
$index = $options['r']-1;
if (!isset($roots[$index]))
{
stderr('There is no entry '.$options['r'].'.');
die($cwd);
}
$old = $roots[$index];
unset($roots[$index]);
file_put_contents($conf, implode("\n", $roots));
stderr('Removed root: ' . $old);
die($cwd);
}
// ---------------------------- find current root dir
$crd = $cwd;
foreach ($roots as $root)
{
if (strpos($cwd, $root) === 0) $crd = $root;
}
dump($crd, 'ROOT: ');
// create regex
$args = array_map('preg_quote', $args);
$regex = '|' . implode('.*', $args) . '|i';
// the last part of the regex has to be the last dir
$regex = '|' . implode('.*', $args) . '[^/]*$|i';
// now search
$temp = $cwd;
$i = 0;
dump('Searching ...');
while (strpos($temp, $crd) === 0 or $crd === false)
{
dump(' '.$temp);
$result = matchDir($temp, $regex, $cwd);
if ($result) die($result);
// if crd is unknown do not do a reverse search
if ($crd === false) break;
// create current search dir (strip last dir)
$temp = substr($temp, 0, strrpos($temp, '/'));
}
// no match so return current dir
stderr('No match found.');
die($cwd);
// this function does not search recursive
function matchDir($dir, $regex, $cwd)
{
$depth = 0;
$stack = array();
$new_stack = @scandir($dir);
foreach ($new_stack as $k => $v)
{
if ($dir == '/') $dir = '';
$actual = $dir . '/' . $v;
if (!is_dir($actual) || $v{0} == '.') continue;
$stack[] = $actual;
}
while (count($stack) > 0)
{
// check first for match
foreach ($stack as $full)
{
if (preg_match($regex, $full) && $full != $cwd) return $full;
}
$depth++;
if ($depth > 5) return false;
// if we got here we had no match
// so put all subfolders to the stack
foreach ($stack as $fullkey => $full)
{
if (!is_readable($full))
{
unset($stack[$fullkey]);
continue;
}
$new_stack = @scandir($full);
foreach ($new_stack as $subdir)
{
$actual = $full . '/' . $subdir;
if (!is_dir($actual) || $subdir{0} == '.') continue;
$stack[] = $actual;
}
unset($stack[$fullkey]);
}
}
return false;
}
function stderr($var) { fwrite(STDERR, print_r($var, true) . "\n"); }
function stdout($var) { fwrite(STDOUT, print_r($var, true) . "\n"); }
function dump($args, $title = null) { if (DEBUG) stderr($title . print_r($args, true)); }
function errorhandler($errno, $errstr, $errfile, $errline) { file_put_contents(__DIR__ . '/cds_error.log', "$errstr\n$errfile ($errline)\n---\n", FILE_APPEND); }
Macht cds ausführbar:
chmod +x ~/bin/cds
Führt dann folgende Zeile auf der Shell aus oder packt sie in eure ~/.bashrc:
c() { cd "`~/bin/cds $@`"; }; complete -o filenames -o nospace -F _cd c
Parameter
-a
-a
Fügt den aktuellen Pfad als root-Pfad hinzu, in welchem auch aufwärts gesucht werden kann.
-l
-l
Zeigt alle root-Pfade an.
-r
-r
Löscht den root-Pfad mit den angegeben Nummer (die aus "c -l")
Viel Spaß und danke fürs Feedback!
Keine Kommentare:
Kommentar veröffentlichen