Skip to content

Instantly share code, notes, and snippets.

@rupa
Created February 23, 2009 07:08
Show Gist options
  • Select an option

  • Save rupa/68838 to your computer and use it in GitHub Desktop.

Select an option

Save rupa/68838 to your computer and use it in GitHub Desktop.
experimental directory navigation
# cd to the shortest, first, non-hidden dir under $root matching all args
#
# USE:
# alias alias=root=root __h [--]
#
# DESCRIPTION
#
# This provides a helper function (__h) meant to be used with aliases to do
# smart directory navigation
#
# The function takes a variable called $root, and uses find to get a sorted
# list of all non-hidden directories under $root. Then, it finds the shortest
# dir that matches all arguments and changes location to it. In the case that
# multiple directories of the same length match, we will cd the first in
# alphabetical order.
#
# If the -- argument is provided, $root is taken to be whichever directory
# you are in one level under root. This is to help with cases where one may
# have many similar subtrees under a directory. See EXAMPLES for a more
# concrete explanation.
#
# EXAMPLES:
#
# # root is /home, doesn't matter where you are located
# alias h="root="/home" __h"
#
# # root is current directory
# alias hh="root="." __h"
#
# # root is /projects/*/, where * is the subdir of /projects you are in.
# # if you are not in a subdir of root, this alias will do nothing
# alias proj="root='/projects' __h --"
# cd to the shortest, first, non-hidden dir under $root matching all args
# careful running it on huge trees :)
# some aliases to get you started
alias h="root="$HOME" __h" # search $HOME
alias hh="root="." __h" # search $PWD
# you aren't expected to use this function directly. use aliases and pass $root.
__h() {
[ "$root" ] || return
if [ "$1" = "--" ]; then
# multiple trees under root - only search current tree
local root=${root%/}/; local p=$(pwd); p=${p#$root}; p=$root${p%%/*}
[ "$p" != "./" -a "$root" = "$p" ] && return
shift
else
# single tree
local p="$root"
fi
[ ! "$1" ] && cd "$p" && return
local cd="$(find "$p" -type d ! -path "*/.*" 2>/dev/null | sort | awk -v q="$*" '
BEGIN { split(q,a," ") }
{
for( i in a ) if( $0 !~ a[i] ) $1 = ""
if( $1 ) if( l ) { if( length($0) < length(l) ) l = $0 } else l = $0
}
END { print l }
')"
[ "$cd" ] && cd "$cd"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment