# Quick directory navigation in the terminal

I would like to frequently switch between directories that are in totally unrelated paths, for example /Project/Warnest/docs/ and ~/Dropbox/Projects/ds/test/.

But I don't want to type cd /[full-path]/ all the time. Are there any shortcut commands to switch to previously worked directories?

One solution I could think of is to add environment variables to .profile for the frequently used directories and cd to them using those variables.

But is there any other solution to this?

-
in office i am using Mac OS X 10.6, which has bash shell.. in home just recently installed UBUNTU and i am not sure what shell it has.. –  saiy2k Feb 8 '12 at 10:45
It has bash - run echo $SHELL. – new123456 Feb 8 '12 at 13:23 Symbolic links could also be useful for this. en.wikipedia.org/wiki/… – user606723 Feb 9 '12 at 15:11 ## 26 Answers If you're just switching between two directories, you can use cd - to go back and forth. - How this has eluded me for so long is a mystery. Thank you very much for this excellent tip. – Mr. Shickadance Feb 9 '12 at 15:21 +1 Certainly one of my favorites and one that somehow many experts have 'missed'. – Michael Durrant Apr 24 '12 at 2:17 There is a shell variable CDPATH in bash and ksh and cdpath in zsh: CDPATH The search path for the cd command. This is a colon-separated list of directories in which the shell looks for destination directories specified by the cd command.  So you can set in your ~/.bashrc: export CDPATH=/Project/Warnest:~/Dropbox/Projects/ds  Then cd docs and cd test will take you to the first found such directory. (I mean, even if a directory with the same name will exist in the current directory, CDPATH will still be consulted. If CDPATH will contain more directories having subdirectories with the given name, the first one will be used.) - It should be mentioned that in general, you'll want the first entry in $CDPATH to be . (an explicitly entry, i.e. : also works). Otherwise you'll end up with the odd behavior where CDPATH dirs take precedence over directories in the current working directory, which you probably do not want. –  jw013 Feb 8 '12 at 23:40
I do pretty much the same thing, but without the export. That way, CDPATH is not exported to scripts with potentially weird or harmful effects. See here for more discussion and examples. –  Telemachus Feb 17 '12 at 12:47
"bash and ksh and cdpath in zsh" ... and in tcsh (just answering a question based on that over on Super User and found this while looking for similar answers on SE). –  Hennes Nov 13 '13 at 7:36
This is POSIX-specified, I think. At least, the POSIX for cd refers to it. –  mikeserv Aug 30 '14 at 17:47

If it's a small number of directories, you can use pushd to rotate between them:

# starting point
$pwd /Project/Warnest/docs # add second dir and change to it$ pushd ~/Dropbox/Projects/ds/test
~/Dropbox/Projects/ds/test /Project/Warnest/docs
# prove we're in the right place
$pwd ~/Dropbox/Projects/ds/test # swap directories$ pushd
/Project/Warnest/docs ~/Dropbox/Projects/ds/test


unlike cd -, you can use this with more than two directories

Following up on Noach's suggestion, I'm now using this:

function pd()
{
if [[ $# -ge 1 ]]; then choice="$1"
else
dirs -v
echo -n "? "
fi
if [[ -n $choice ]]; then declare -i cnum="$choice"
if [[ $cnum !=$choice ]];
then #choice is not numeric
choice=$(dirs -v | grep$choice | tail -1 | awk '{print $1}') cnum="$choice"
if [[ -z $choice ||$cnum != $choice ]]; then echo "$choice not found"
return
fi
fi
choice="+$choice" fi pushd$choice
}


example usage:

# same as pushd +1
$pd 1 # show a prompt, choose by number$ pd
0 ~/Dropbox/Projects/ds/test
1 /Project/Warnest/docs
2 /tmp
? 2
/tmp ~/Dropbox/Projects/ds/test /Project/Warnest/docs

# or choose by substring match
$pd 0 /tmp 1 ~/Dropbox/Projects/ds/test 2 /Project/Warnest/docs ? doc /Project/Warnest/docs /tmp ~/Dropbox/Projects/ds/test # substring without prompt$ pd test
~/Dropbox/Projects/ds/test /Project/Warnest/docs /tmp


etc. Obviously this is just for rotating through the stack and doesn't handle adding new paths - maybe I should rename it.

-
Ooh, I knew about pushd and popd for traversal, but not that pushd could rotate what's been used so far... –  Izkata Feb 8 '12 at 20:29

Something else you might try is a tool called autojump. It keeps a database of calls to it's alias (j by default) and attempts to make intelligent decisions about where you want to go. For example if you frequently type:

j ~/Pictures


You can use the following to get there in a pinch:

j Pic


It's installed system-wide, but included on a per-user basis in ~/.bashrc or ~/.zshrc by default.

-
Autojump is probably the best tool for this, it takes a little while to build up the database of common dirs, but once it does I think you'll find that you can't live without it. I know every time I'm on someone else's computer I feel crippled. –  quodlibetor Feb 13 '12 at 18:29
thanks love this tool! And although cd - is handy to know if you don't already know it, I think this is a much better solution than the current top answer. –  User Oct 13 '14 at 4:49

Try the cdable_vars shell option in bash. You switch it on with shopt -s cdable_vars.

Then you need to set your variables export dir1=/some/path. and finally cd dir1, etc. You can then put it in your ~/.bashrc to make it stick.

-

I found a script that solved this issue for me. With this you can type cd -- to see the last 10 directories that you've used. It'll look something like this:

0  ~/Documents/onedir
1  ~/Music/anotherdir
2  ~/Music/thirddir
3  ~/etc/etc


To go to ~/Music/thirddir just type cd -2

http://www.geocities.com/h2428/petar/bash_acd.htm

-
The very same script was also published in the Linux Gazette, Issue #109, December 2004. –  Serge Stroobandt Jun 20 '13 at 21:12
@Dean The link goes to a music video and says that Geocities has closed. –  somethingSomething Aug 30 '14 at 15:05

I use alias in bashrc to do those cds.
such as:

alias wdoc='cd ~/Project/Warnest/docs'
alias dstest='cd ~/Dropbox/Projects/ds/test'

-
is bashrc a file like .profile? in which I need to add those lines? –  saiy2k Feb 8 '12 at 7:43
~/.bashrc or /etc/bash.bashrc. I did not use .profile before, so don't know the relationship between them :-( –  Felix Yan Feb 8 '12 at 7:45
scripts bashrc will start everytime you open terminal. profile with startup. –  user14517 Feb 8 '12 at 10:42
added those lines to my .bash_profile and it works great.. thx :) –  saiy2k Feb 8 '12 at 10:56

The following appeared to work on the one case I tested it on, and you can just drop your directory names as symlinks in ~/Bookmarks:

mkdir "$HOME/Bookmarks" ln -s /tmp "$HOME/Bookmarks/testdir"

function ccd() { cd $(readlink "$HOME/Bookmarks/$1") ; } ccd testdir && echo$PWD
# gives /tmp

-
that ccd() function need to typed in the terminal prompt or somewhere else? can u pls explain? –  saiy2k Feb 8 '12 at 8:41
@saiy2k: sorry, yes. The function line goes into your .bashrc (you can type it in your terminal to test, but it'll be gone when you close that window), the lines before set up the test case of "testdir" becoming a name for /tmp, and the last line is the test to see if it works. –  Ulrich Schwarz Feb 8 '12 at 17:19

There are a lot of good suggestions here. Which to use would depend on whether you have a small fixed list of directories you switch among, or whether you are looking for a more generic solution.

If it's a small fixed list, setting up simple aliases (as Felix Yan suggested) would be easiest to use.

If you're looking for a more generalized solution (i.e. many different directories, changing over time), I'd use pushd and popd (as Useless suggested). I personally find the default pushd/popd to be hard to use, especially as you start switching among many folders; however I wrote a few tweaks that make it much easier for me. Add the following to your bashrc:

alias dirs='dirs -v'
pd ()
{
if [ "$1" ]; then pushd "${1/#[0-9]*/+$1}"; else pushd; fi > /dev/null }  • Use pd (as a shorter form of pushd) to jump to a new folder, remembering where you were. • Use dirs to see the list of saved directories. • Use pd 3 to jump to directory number 3. Example Usage: $ PS1='\w\$' ## just for demo purposes ~$ pd ~/Documents/data
~/Documents/data$pd ../spec ~/Documents/spec$ pd ~/Dropbox/Public/
~/Dropbox/Public$pd /tmp /tmp$ pd /etc/defaults/
/etc/defaults$dirs 0 /etc/defaults 1 /tmp 2 ~/Dropbox/Public 3 ~/Documents/spec 4 ~/Documents/data 5 ~ /etc/defaults$ pd 2
~/Dropbox/Public$dirs 0 ~/Dropbox/Public 1 ~/Documents/spec 2 ~/Documents/data 3 ~ 4 /etc/defaults 5 /tmp ~/Dropbox/Public$ pd 4
/etc/defaults$dirs 0 /etc/defaults 1 /tmp 2 ~/Dropbox/Public 3 ~/Documents/spec 4 ~/Documents/data 5 ~ /etc/defaults$ pd 3
~/Documents/spec$popd ~/Documents/data ~ /etc/defaults /tmp ~/Dropbox/Public ~/Documents/data$

-
I see ... more pushd wrappers in my future :-) –  Useless Feb 8 '12 at 23:15

You could do worse than try j2.

Spend a lot of time cd-ing around a complex directory tree?

j keeps track of where you’ve been and how much time you spend there, and provides a convenient way to jump to the directories you actually use.

I use it extensively & recommend it.

-

I'd advice using zsh, that shell as very good TAB completion for directories, files, and even options for most cli programs.

I've been using that shell for years now, and I'd miss the functionality if it was gone. Scripting the zsh is a lot of fun, too, with a large number of one-liners that can help you every day.

-
No need to change to zsh for TAB completeion since bash has it all the same. For other functionality maybe but not for this. –  Peer Stritzinger Feb 9 '12 at 11:14
@PeerStritzinger Bash introduced that kind of functionality in BASH 4.0, but compared to zsh, it is still quite far behind. Saying "all the same" is certainly incorrect. –  polemon Feb 22 '12 at 0:02
Well zsh is ceartainly the übershell but just for tab completion there is no need to change (question was asked for bash). Besides bash 4.0 was introduced about 3 years ago ... –  Peer Stritzinger Feb 22 '12 at 9:45

There's also OLDPWD, an environment variable which, according to IEEE 1003.1 (POSIX), should be updated with the previous working directory each time cd changes the working directory (for the curious ones, line 80244 of page 2506 of IEEE 1003.1-2008).

-

if you're using zsh:

• you don't have to type cd, just type directory path (/foo/bar/baz<Enter> equals to cd /foo/bar/baz<Enter>)

requires auto_cd option to be set

• you can expand abbreviated paths with Tab key (/u/sh/pi<Tab> expands to /usr/share/pixmaps; works for file names as well)
-
Bash 4 has gained shopt -s autocd, so it's no longer a zsh-only goodness. –  Gilles Feb 8 '12 at 23:44

Use "pushd -n" (assuming you use bash).

pushd -n /Project/Warnest/docs/
pushd -n ~/Dropbox/Projects/ds/test/


then,

cd ~ is your home,

cd ~1 is ~/Dropbox/Projects/ds/test/

cd ~2 is /Project/Warnest/docs/

You can use ~1,~2 etc in exactly the same way as ~.

-

There is a rather nice tool for quick directory changes:

xd - eXtra fast Directory changer http://xd-home.sourceforge.net/xdman.html

a bit awkward is that you need to map it in bash profile or similar as it only outputs the directory

# function to do cd using xd
# -g turns generalized directory search command processing on
# which improves the whole thing a bit
f()
{
cd /usr/bin/xd -g $* }  you can do things like: # change to /var/log/a* (gives you a list to choose from) f vla # to skip the list and go directly to /var/log/apache2 f vlapach  - cdargs is the most efficient tool for bookmarking a directory: http://www.youtube.com/watch?v=uWB2FIQlzZg - Is this a product you are associated with? – Kazark Feb 27 '13 at 19:21 Thanks for pointing me to cdargs. Simply sudo apt-get cdargs on ubuntu. BTW the youtube video is really bad but the tool is great. – DavidG Jul 21 '14 at 16:00 There is also a "wcd" app created specifically for this (also ported to cygwin, since I am on that). You can create shortcuts, bookmarks of dirs with it. Also supports wild cards. Reading the man page & docs in /usr/share/wcd should help a lot. http://manpages.ubuntu.com/manpages/hardy/man7/wcd.7.html - Some suggestions here: Most direct idea, I will add alias in the .profile file vi ~/.profile alias dir1='cd /myhome/onedir' alias dir2='cd /jimmy/anotherdir'  Then use $ dir1 or dir2, can cd

If you are always switching in two dirs only. using cd - will switch between them.

-

In my experience, the greatest speedup in navigating in a shell is to use its history search functionality. In Bash you can search backwards in your history of commands by pressing Ctrl+R and type in some pattern. That pattern is then matched against previous entries in your history -- may it be cd commands or other operations -- and suggestions are made as you type. Simply hit enter to run the suggested command again. This is called reverse-search-history in Bash and I love it. It saves me a lot of keystrokes and spares my internal memory.

It's a good thing because you only have to remember some smaller part of a command, like Drop or Wa to distinguish between the two history entries cd ~/Dropbox/Projects/ds/test/ and cd /Project/Warnest/docs/.

-

I've been using my own utility to manage this for many years. It aliases your cd command and automatically keeps a directory stack.

-

I also use these aliases (add them to ~/.bashrc):

alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias .....='cd ../../../..'


It's much quicker to go to the upper directory with them (yet it only solves half of the navigation).

-
These are helpful aliases, but I'm not entirely sure that they will match the OP's needs. You might consider expanding on your answer to suggest how these might be directly helpful for the OP's issue. –  HalosGhost Jul 11 '14 at 18:36

Try fastcd (https://github.com/frazenshtein/fastcd) It sets hook that records visited directories from bash. And sets script as "j" alias, that shows you the last visited directories, with the ability to quickly cd (start typing to filter directories). Modification of .bashrc is required to make the "j" alias.

Getting tool

cd ~; mkdir Soft; cd Soft
git clone https://github.com/frazenshtein/fastcd


Install required modules

pip install --user urwid


Source the set.sh file into your bashrc

echo -e "\nsource /home/$USER/Soft/fastcd/set.sh\n" >> ~/.bashrc  And update bashrc source ~/.bashrc  Then just type "j" in console - How does this work? If it's aliases, what does this tool do for you that you can't do by manually editing .bashrc? – G-Man Nov 3 '14 at 22:55 It launches daemon that records visited directories in ~/.fastcd for launched shells(bash). "j" launches tool that shows you the last visited directories, with the ability to quickly cd. Modification of .bashrc is required to make the "j" alias. You can see source code for more information, i guess – Sam Toliman Nov 3 '14 at 23:36 Thanks for your quick response. This is the sort of information that should be in the answer. Please edit your answer to include this info. – G-Man Nov 4 '14 at 15:21 working directory(wd) from atomic seems to be a good package for this: https://github.com/karlin/working-directory - The solution I use for this situation is screen. Start screen and create a window for each directory with C-a c and navigate there. Change between windows/directories with C-a n or C-a p. Name the windows with C-a A. Then you can pop up a list of your windows with C-a " and navigate using the window number or name. Since it is screen, you can detach from the session saving your work space and re-attach later with the same set up. - You never ever should type full path in shell anyway. You always can use: soffice /P*/W*/*/mydoc*  instead of soffice /Project/Warnest/docs/mydoc.odt  - I never did like pushd and popd because they require foresight. Screw that, let's just keep track of the last several directories on our own and then make them available with a cd-to-old-dirs function. I call it cdo. Put this in your rc file (e.g. ~/.bashrc): function precmd() { __path_log; } # to install in zsh, harmless in bash PROMPT_COMMAND="__path_log" # to install in bash, harmless in zsh # Populate the array DIRHIST with the last 8 dirs visited (not for direct use) __path_log() { local d dh first=true if [ -d "$__DIRHIST" ] && [ "$__DIRHIST" != "$PWD" ]; then
# $__DIRHIST is the last dir we saw, but we miss foo in 'cd foo; cd bar' # so we use$OLDPWD to catch it; so you'd need a THIRD change to fool us.
for d in "$__DIRHIST" "${DIRHIST[@]}"; do
if [ -n "$first" ]; then unset DIRHIST first; DIRHIST[1]="$OLDPWD"; fi
if [ "$OLDPWD" = "$d" ] || [ "$PWD" = "$d" ] || [ ! -d "$d" ]; then continue fi dh=$((1+${#DIRHIST[@]})) [$dh -lt 9 ] && DIRHIST[$dh]="$d" # push up to 8 directories
done
elif [ -z "$__DIRHIST" ]; then DIRHIST[1]="$OLDPWD"
fi
__DIRHIST="$PWD" } cdo() { local d n=0 if [ -z "${DIRHIST[1]}" ] || [ -z "$1" ]; then cd${OLDPWD+"$OLDPWD"} return$?
fi
case "$1" in 0 ) cd ;; ls ) for d in "${DIRHIST[@]}"; do
echo "$((n=n+1)) <$d>"
done |column |GREP_COLOR='0;32' grep --color -e '\b[0-9] <' -e '>'
;;
[1-9]) cd "${DIRHIST[$1]}" ;;
* )    echo "Usage: cdo [NUM|ls]" >&2; return 2 ;;
esac
}


The following example uses a prompt of hash directory dollar (# dir $), chosen because Stack Overflow will make prompts gray: # ~$ cd /tmp
# /tmp $cdo # ~$ cdo ls
1 </tmp>
# ~ $cd / # /$ cdo ls
# / $cdo # ~$ cdo ls
1 </>   2 </tmp>
# ~ $cdo 2 # /tmp$ cd test
# /tmp/test $cd ../test2 # /tmp/test2$ cdo ls
# /tmp/test2 $cdo 4 # /$ cd

It's really neat to see that other people have had the same general idea as me (I thought I had been original!). @SamTroliman's mention of fastcd, @null's xd, and @phildobbin's j2 all look quite similar. See also duplicate question 84445, which has a zsh answer using setopt auto_pushd. I still prefer my own code, but ymmv.