top | item 2237595

Don't waste your time by cd-ing in the terminal

449 points| siim | 15 years ago |huyng.com

118 comments

order

mtrn|15 years ago

Don't waste your time bookmarking directories, jump right to them ;) https://github.com/rupa/z

`z` tracks your most used directories. After a short learning phase, it will take you to the directory, based on its usage frequency and a hint you give it on the command line. Say I am often cd'ing into /var/www - then after a while I can just type `z ww`.

SwellJoe|15 years ago

I love projects like this. They so elegantly show what using the right tool for the job can do for you, in terms of code simplicity and conciseness. Doing this in, say, Perl or Python or Ruby, would be entirely possible, and folks who code exclusively in those languages might assume it would be easier in a "more powerful" language...but Bash has so many nice little built-ins that make it really concise and portable. One file, no modules, and it does exactly what it's supposed to do.

I think it's illustrative that the developer went through a Python-based version on the path to building z.

webXL|15 years ago

I want to be able to preview the path or directory name that z will navigate to. Something like the way the webkit developer console autocompletes an object, method, or property in light gray color. Or it could be displayed in the terminal title bar. Is that possible?

dekz|15 years ago

I remember seeing this, but forgot entirely to use it. Have been spending a while looking for it again, or something equivalent. Thanks.

alanh|15 years ago

I like this workflow better:

1. Go to the directory in question

2. Type "save nm" where "nm" is any short name for the directory, like "blog" or "blg"

3. From now on, type "cd nm" whenever you want to go there.

No session restart required, even.

I copied the code that enables this workflow from http://dotfiles.org/~jacqui/.bashrc (or was it https://gist.github.com/117528)

The idea is discussed here: http://hints.macworld.com/article.php?story=2002071600512379...

sjs|15 years ago

Or in zsh:

    setopt cdablevars
    nm=/path/to/whatever
    cd nm

hyperbovine|15 years ago

Dollars to donuts the author is a Vimmer. I am and the workflow makes complete sense to me :-)

anon_d|15 years ago

Why not just:

    echo "export nm=`pwd`/blog"' >> ~/.profile
    . ~/.profile
    cd $nm
There's no need for magic when you know how to shell.

huyegn|15 years ago

Hey Guys,

This is my blog.

FWIW, I've actually switched away from using the script mentioned in the link posted by OP and have moved towards using an improved version below.

http://www.huyng.com/bashmarks-directory-bookmarks-for-the-s...

This new version has 3 commands:

    - "s" for save current directory as a bookmark
    - "g" for jump to bookmark's directory
    - "l" for list all bookmarks.

philikon|15 years ago

I first was excited by title "Don't waste your time by cd-ing in the terminal", but then it just turned out to be a blog post about making cd'ing quicker. If you want to boost your productivity, my advice is to stop cd'ing altogether.

I see a lot of people -- particularly vi users -- cd'ing back and forth through a large directory tree. I usually tell them to get a terminal emulator that lets you easily manage many terminals open. Open one per directory you want to operate in, for instance. Learn how to switch back and forth between the different shells.

But most importantly, don't quit the program to switch back and forth between directories and files. Learn to use your editor of choice properly: how to view directory listings, how to switch back and forth, etc. Vim can do this just fine btw. The choice of tool here doesn't matter so much. Just pick one and learn it. This applies to your choice of terminal emulator, shell, editor, etc.

moe|15 years ago

Open one per directory you want to operate in, for instance.

This is a common source of headache when using the terminal as an IDE. Not only is it easy to get lost in a sea of terminal-tabs, but it's also quite cumbersome to restore the state of 5+ tabs after a shutdown or disconnect. Even more so when GNU screen enters the mix.

What I'd really like to have is a terminal that can attach to a remote GNU screen and display the screen-windows as local tabs.

erikrose|15 years ago

Also, pushd and popd. And "cd -". And ctrl-Z and fg to jump out of your editor for a moment. And dragging dirs from the Finder (or whatever) to the terminal.

holygoat|15 years ago

And use tools that are aware of directories: tar -C, NERDtree for Vim, zsh globbing.

thet|15 years ago

a terminal emulator which has a session sasving feature built in to restore terminal tabs with their working directories is: termit find it on github. lua scripting api included :)

cldwalker|15 years ago

Why is a home-rolled cd script interesting when there are many more mature, feature-rich cd-tools out there?

* http://www.skamphausen.de/cgi-bin/ska/CDargs

* http://micans.org/apparix/

* http://github.com/joelthelion/autojump

* http://github.com/rupa/z

* http://github.com/flavio/jump

Also, the title is misleading. I thought it was actually a commandline tool that removed the need to cd most of the time, like lightning: http://tagaholic.me/2010/04/08/lightning-speed-for-your-shel...

medwezys|15 years ago

Ditto, this one feels like reinventing the wheel when we have the tools you named.

julian37|15 years ago

Yet another time saver: if you need to execute only a single command in another directory, use:

  (cd /path; command)
This will cd to /path, run command, but return you to your original working directory. This works because the parens create a sub-process, and the cd command only affects that sub-process.

semanticist|15 years ago

I prefer (cd /path && command), since that way if the cd fails for some reason (like you've typo'd the path), it won't still attempt to run the command.

technomancy|15 years ago

Appending ";cd -" on the end will have the same effect.

substack|15 years ago

There's also the pushd and popd commands which are part of bash already.

And there's a wikipedia entry for this even: http://en.wikipedia.org/wiki/Pushd_and_popd

miratrix|15 years ago

You can also use the "dirs" command (I think part of bash as well) that tells you the state of the stack. If you set the -v option, you can get the depth of different directories, and you can just do pushd +N to jump to the specific directory.

bretthopper|15 years ago

No mention of ZSH directory stacks yet? http://www.acm.uiuc.edu/workshops/zsh/dir_stack.html

Some helpful aliases to manage them:

alias 1='cd -1'

alias 2='cd -2'

alias 3='cd -3'

alias 4='cd -4'

alias 5='cd -5'

alias 6='cd -6'

alias 7='cd -7'

alias d='dirs -v'

alias h='history'

alias j='jobs'

Just one of the many reasons to use ZSH.

jrockway|15 years ago

Just one of the many reasons to use ZSH.

What shell doesn't have a directory stack?

ringm|15 years ago

I have bound 'pushd -1' to PgUp.

    function directory_up { 
      pushd -1
      zle reset-prompt 
    }
    zle -N directory-up directory_up
    bindkey "\e[5~" directory-up
Ditto for "pushd +0" and PgDn.

sjs|15 years ago

How about `setopt cdablevars`?

    setopt cdablevars
    proj=$HOME/Projects
    cd proj
    pwd # => /Users/sjs/Projects

nolite|15 years ago

nice stuff. You got your dotfiles on a github?

kevinburke|15 years ago

dlwh|15 years ago

Just to help sell it some more: autojump basically watches where you cd and builds a model (of some sort) that guesses where you want to go based on a few characters.

For instance, I have a project called "structured-prediction" deep in some folder hierarchy, and I can just type "j stru" or "j pred" or even "j uct" and it goes to the directory.

The best part is that it figures this out automatically. You don't have to remember to bookmark anything.

lars512|15 years ago

Agreed, autojump seems far more principled too than the method described in OP.

askedrelic|15 years ago

Autojump is my vote as well

jongraehl|15 years ago

I also prefer autojump.

aheilbut|15 years ago

I've also wondered to myself why there isn't a terminal program with a directory tree by the side so you could just click on the directory that you want to be in, instead of ls -cd-tab-blah-^H-tab-^M. It would also a have a list of favorite and most-recently-used directories.

A weekend project, perhaps...

xd|15 years ago

Because clicking a mouse takes you away from the keyboard .. a context switch if you like, which added up over time slow you down when you have work to do.

l0nwlf|15 years ago

Unrelated but a nice alias "tree".

alias tree="find . -name .svn -prune -o -name .DS_Store -prune -o -name .git -prune -o -print | sed -e 's;[^/]*/;|___;g;s;___|; |;g'"

It shows your directory listing in the form of a tree. Easier to visualize.

narkee|15 years ago

Because that would require a mouse, and that would require an X server, etc...

pbhjpbhj|15 years ago

I use Dolphin sometimes for this reason, so that I can navigate the directory tree/places via mouse but use the console pane as normal.

Krusader also has a built in console pane.

Not strictly a terminal as the console is running over KDE over X, ..., but works for me.

xd|15 years ago

Maybe not as quick .. but `ctrl+r cd` gets me there quick enough and I don't have to remember what numeric shortcut is assigned to which directory.

Will give it a shot however, good effort.

gnubardt|15 years ago

Another time saver is to have a function that calls ls after cd'ing:

  c(){ cd "$@" && ls;}
This has probably saved me days over the years, as I almost always want to list a directory after I change into.

l0nwlf|15 years ago

Silly me. I almost always do the same, but never thought of creating a function. Thanks anyways. :D

telemachos|15 years ago

Another built-in worth knowing about is CDPATH.[1] I find that setting a sane CDPATH and bash-completion makes cd-ing anywhere I go regularly pretty trivial - just a few letters and a few TABs and I'm good to go.

[1] http://caliban.org/bash/#bashtips

moe|15 years ago

I'd be extremely careful with CDPATH, never use this on an important host.

Having "cd foo" potentially take you to an entirely different location can be dangerous, to say the least.

coenhyde|15 years ago

I use this function in my bash profile to navigate to my projects from anywhere on the file system.

  function to {
    cd ~/Sites/$1/
  }
eg. cd ~/Sites/coenhyde.com

$ to coenhyde.com

orlandu63|15 years ago

I would suggest mapping an alias instead of creating a function so that you will still be able to take advantage of parameter completion:

> alias to='cd ~/Sites/'

nevinera|15 years ago

    alias ba='vim ~/.bash_aliases; source ~/.bash_aliases'
Just make aliases for all the directories you go to a lot. I have twenty-something different aliases that start with 'cd'.

A bookmarking system seems like overkill to solve this problem.

oemera|15 years ago

Thank you for this awesome little script. However I found out that bashmarks doesn't work with folders which have whitespaces in the name.

For example:

  cd /Users/username/Library/Application\ Support
  s app_support
works great but if you do this it won't work:

  g app_support
I opened an issue on GitHub and after that I tried to fix it on my own. I never wrote a bash script and I'm really proud to have fixed this problem on my own.

Here are changes I made:

  # save current directory to bookmarks
  touch ~/.sdirs
  function s {
     cat ~/.sdirs | grep -v "export DIR_$1=" > ~/.sdirs1
     mv ~/.sdirs1 ~/.sdirs

     escaped_path=${PWD/ /\\ }
     echo "export DIR_$1=$escaped_path" >> ~/.sdirs
  }

  # jump to bookmark
  function g {
     source ~/.sdirs
     path=$(eval $(echo echo $(echo \$DIR_$1)))
  
     # replace whitespaces with "\ " for escaping
     escaped_path=${path/ /\\ }
     cd_eval="cd $escaped_path"
    
     eval $cd_eval
  }
Hope this helps you guys like it helped me. And if there is a way to do this in an more elegant way, please let me know. This would help me to improve my none existing bash skills :D

Edit: I opened up a fork and commited all my changes to this repo. I also opened a pull request and I hope my fix will get accepted.

GitHub fork: https://github.com/Oemera/bashmarks

Thanks

Ă–mer

noibl|15 years ago

I was just at the point of making a bunch of aliases for some long paths, to save my tab key from daily abuse. This is way more elegant. Thanks.

wanderr|15 years ago

Maybe it's just because I run a lot of the same commands and don't do a lot of development from the terminal, but I avoid cding at all usually and just type the full path. It svaes time over multiple sessions thanks to ctrl+r, and the commands in my history work no matter what dir I'm in.

pieceofpeace|15 years ago

Ctrl-r is what I use too. Usually requires fewer keystrokes than other methods discussed here. And it works for all commands in shell history.

Groxx|15 years ago

A nice idea... I may end up using it, though a lot of my folders are the same name and I do like deterministic behavior.

In the meantime, this kicks the pants off separate Finder + Terminal action: http://decimus.net/DTerm/

sayemm|15 years ago

Interesting reading this because this is exactly why I love emacs, especially when I came across this tip a while ago: "Emacs: TRAMP + bookmarks = awesome", http://marc-abramowitz.com/archives/2006/03/12/emacs-tramp-b...

I'm always plugged in to my server with tramp and I've got multiple projects all bookmarked. It makes hopping around real easy, makes it feel like a browser more than an editor.

charlieroot|15 years ago

1. How about we just learning to type fast(-er) and use file name completion

2. Use real shell like ksh, where history search actually works

3. cd $OLDPWD is occasionally helpful. Occasionally.

Kids...

ajslater|15 years ago

Exactly. OP is doing gymnastics to solve a non-problem.

iclelland|15 years ago

Is 'cd $OLDPWD' any different from 'cd -' ?

clu3|15 years ago

I have usually a few dirs that i go back and forth frequently when coding, and I simply set them to my env. I add the following line to ~/.bashrc export lib='/path/to/my/lib' And 'cd $lib' will take me there. Very simple, and caters for most of my cd needs. Don't over-complicate things

rlpb|15 years ago

I use "m1=`pwd`" and then "cd $m1" for example. No setup required, although admittedly slightly more typing and the need to quote directories with spaces in them (rare for Unix sysadmin tasks for which I'm using a shell in the first place).

adsr|15 years ago

I manage with a combination of pushd/popd, cd - and terminal tabs most of the time.

netghost|15 years ago

If you're a programmer, you may find Qwandry useful: github.com/adamsanderson/qwandry

Instead of trying to remember where all your libraries are located, it will just open them up for you. Great for trying to debug misbehaving code.

philc|15 years ago

Additionally, try typing fewer characters when you cd in the general case: https://github.com/philc/fuzzycd

I've been using this for a few years and it's been a joy.

bherms|15 years ago

I use textexpander to keep from cd'ing everywhere... Just stick in a text expander snippet for directories I use a lot...

ie: hwst - cd /usr/Brad/Desktop/Dropbox/Brad/howas.it/repos/howasit_alpha/ etc...

slowpoison|15 years ago

The suggestion about putting "mdump" in .bash_logout, to automatically save all your bookmarks on exiting shell, is really useful.

pentarim|15 years ago

I cant remember my bookmarks so CTRL + R, then searching in history most of a time

jesstaa|15 years ago

Why not just use symlinks for your bookmarks? pushd and popd are also useful.

Nick_C|15 years ago

I got bitten with symlinks for bookmarks. They don't change the PWD to the correct one. For example:

  cd /home/nick
  ln -s /var/www www
  cd www
  echo $PWD --->  /home/nick/www
which will break scripts.