I find myself, like most developers, spending a lot of time navigating directories. Flipping back and forth between logs and application directories with long names can be quite tedious. So, with the help of a few new functions, aliases and config tweaks I've made the navigation process easier and more efficient. You no longer need to remember long paths because you can jump straight to them using their names. You can also choose to bookmark your favourite directories. Here is my setup:
1. Go up to a specific directory
I have a function called upto
which allows you to jump up to any directory, on the current path, just by name. This is very useful if you are deep in a directory. I also have autocompletion for this function, so that it shows me valid directory names and completes them for me.
#
# Go up to the specified directory
#
upto(){
if [ -z $1 ]; then
echo "Usage: upto [directory]"
return 1
fi
local upto=$1
cd "${PWD/\/$upto\/*//$upto}"
}
#
# Completion function for upto
#
_upto(){
local cur=${COMP_WORDS[COMP_CWORD]}
d=${PWD//\//\ }
COMPREPLY=( $( compgen -W "$d" -- $cur ) )
}
complete -F _upto upto
Example:
[/www/public_html/animals/hippopotamus/habitat/swamps/images] $ upto h[TAB][TAB]
habitat hippopotamus
[/www/public_html/animals/hippopotamus/habitat/swamps/images] $ upto hippopotamus
[/www/public_html/animals/hippopotamus] $
2. Go up a specific number of directories
If you know how many levels you want to go up, you can use the up
function e.g. up 5
will move you up 5 directories.
#
# Go up a specified number of directories
#
up(){
if [ -z $1 ]
then
cd ..
return
fi
local levels=$1
local result="."
while [ $levels -gt 0 ]
do
result=$result/..
((levels--))
done
cd $result
}
3. Go down to a specific directory
Sometimes you want to change to a directory but can't remember the path, or the path name is too long to type. I have a function called jd
which allows you to jump down to a directory any level below the current one. It uses Bash's globstar feature so make sure you have it enabled (using shopt -s globstar
). (Warning: this may be slow on large directory structures because of the searching involved.)
#
# Jumps to a directory at any level below.
# using globstar
#
jd(){
if [ -z $1 ]; then
echo "Usage: jd [directory]";
return 1
else
cd **/$1
fi
}
Example:
[/www/public_html/animals/hippopotamus/habitat/swamps/images] $ upto hippopotamus
[/www/public_html/animals/hippopotamus] $ jd images
[/www/public_html/animals/hippopotamus/habitat/swamps/images] $
4. CDPATH
The CDPATH
variable is a colon-separated list of directories in which the shell looks for destination directories specified by the cd
command. Mine is shown below. No matter what directory I am currently in, I can quickly jump to a project in my dev directory with cd <project>
because it is on my path.
export CDPATH=".::..:../..:~:~/dev/"
5. Shell Options
I have set the following useful shell options in my .bashrc
. The autocd
option allows you to change to a directory without using the cd
command and cdspell
automatically corrects typos in directory names.
shopt -s cdspell # correct dir spelling errors on cd
shopt -s autocd # if a command is a dir name, cd to it
shopt -s cdable_vars # if cd arg is not a dir, assume it is a var
6. Quick Aliases
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias .....='cd ../../../..'
alias ......='cd ../../../../..'
7. Keeping a history of visited directories
I came across a useful post on Linux Gazette: History of visited directories in BASH. It contains a script which maintains a history of directories you have visited and then allows you to switch to them easily using a reference number. The command cd --
shows you your history and cd -2
would take you to the second item in your history list. For example:
[/www/public_html/animals] $ cd --
1 /tmp
2 /www/public_html/animals/hippopotamus/habitat/swamps/images
3 /www/public_html/animals/lion
[/www/public_html/animals] $ cd -2
[/www/public_html/animals/hippopotamus/habitat/swamps/images] $
8. Bookmarks
I spend a lot of time moving between different directories especially between logs and application directories. I have implemented a bookmarking feature which allows you to bookmark your favourite directories and then change to them easily.
bm
: bookmark the current directory
bcd
: change to the specified bookmark
brm
: remove a bookmark
bcl
: clear all bookmarks
bll
: list all bookmarks
#-------------------------------
# Directory Bookmark Functions
#-------------------------------
#
# Add a bookmark, if it doesn't exist
#
bm(){
local val=$(pwd)
for i in ${bookmarks[@]}
do
if [ "$i" == "$val" ]
then
return 1
fi
done
num=${#bookmarks[@]}
bookmarks[$num]=$val
}
#
# Goto specified bookmark
# or previous one by default
#
bcd(){
index=$1
if [ -z $index ]
then
index=$((${#bookmarks[@]}-1))
fi
local val=${bookmarks[$index]}
if [ -z $val ]
then
echo "No such bookmark. Type bll to list bookmarks."
return 1
else
cd "$val"
fi
}
#
# Remove a bookmark
#
brm(){
if [ $# -lt 1 ]
then
echo "Usage: brm [bookmark-index]"
return 1
fi
if [ -z ${bookmarks[$1]} ]
then
echo "No such bookmark"
return 1
fi
bookmarks=(${bookmarks[@]:0:$1} ${bookmarks[@]:$(($1 + 1))})
}
#
# Remove all bookmarks
#
bcl(){
bookmarks=()
}
#
# List all bookmarks
#
bll(){
if [ ${#bookmarks[@]} -ne 0 ]
then
local i=0
while [ $i -lt ${#bookmarks[@]} ]
do
echo $i: ${bookmarks[$i]}
((i++))
done
fi
return 0
}
If you have any useful directory-related functions, share them in the comments below!
Related Posts: