Insights on Ruby, Git, jQuery, Cappuccino, WordPress, Debian and OS X. Please subscribe if you find something useful!

cd up, up, and a-up

Posted: September 7th, 2009 | Author: Jerod | Filed under: Tools | View Comments

Command-line jockeys are intimately familiar with the cd command. We’ve typed commands like this one a gozillion times:

jerod@mbp:~/src/ruby/rails$ cd ..
jerod@mbp:~/src/ruby$

We all know that . represents the current working directory and .. represents the current working directory’s parent directory. If we follow this pattern to its logical conclusion, then would represent the current working directory’s parent’s parent, etc. Unfortunately, cd doesn’t work that way.

jerod@mbp:~src/ruby/rails$ cd ...
-bash: cd: ...: No such file or directory
jerod@mbp:~$

Total bummer!

Instead, we have to repeat ourselves for every directory up we want to move. So, we end up typing commands that look like this:

jerod@mbp:~/src/ruby/rails$ cd ../..
jerod@mbp:~/src$

The more directories up to move in the file system, the more ridiculous the command becomes:

jerod@mbp:~/src/ruby/rails/box-office/app/models$ cd ../../../../..
jerod@mbp:~/src$

*note* - in this contrived example, cd ~/src would be a much better way of navigating

If you’ve ever typed a command like that one, you feel my pain. I put up with this for a long time, but I’ve finally had enough of it. Here is a simple bash function that allows us to simply append .‘s to the cd command for each directory we want to move up.

bad_function

*update*some guy pointed out that my function didn’t correctly handle pathnames with spaces in it and he was kind enough to supply a simplified function to the one I wrote.

1
2
3
4
5
6
7
8
9
10
11
12
13
function cd () {
  if [[ $# > 0 ]]; then
    if [ ${1:0:2} == '..' ]; then
      rest=${1:2}
      rest=${rest//./../}
      builtin cd "${1:0:2}/${rest}"
    else
      builtin cd "$1"
    fi
  else
    builtin cd
  fi
}

This is a simple wrapper function that ends up calling the shell’s built-in cd command. Drop it in your .bashrc or .bash_profile and give it a whirl!

jerod@mbp:~/src/ruby/rails$ cd ...
jerod@mbp:~/src$

Much better!

p.s. – I added this function to my .bashrc which I store in a dotfiles repo on GitHub. Feel free to check it out and see if there’s any other useful tricks you can add to your command-line répertoire.


View Comments on “cd up, up, and a-up”

  1. 1 someguy said at 8:02 am on September 8th, 2009:

    This seems unnecessarily complicated. It's also not safe for pathnames with spaces or other shellcandy. Try:

    function cd () {
    if [ ${1:0:2} == '..' ]; then
    rest=${1:2}
    rest=${rest//./../}
    builtin cd “${1:0:2}/${rest}”
    else
    builtin cd “$1″;
    fi
    }

  2. 2 sant0sk1 said at 8:52 am on September 8th, 2009:

    You're absolutely right, my function doesn't handle spaces in pathnames at all. I'll give yours a try and if it works as advertised I'll be using it instead, thanks!

    I'm not familiar with:

    ${1:0:2}

    What does that mean?

  3. 3 someguy said at 11:10 am on September 8th, 2009:

    ${foo:x:y} == foo[x:y] in Python.

  4. 4 sant0sk1 said at 2:03 pm on September 8th, 2009:

    So you're accessing a subset of $1. That makes sense.

    Your function works great in every situation except when you don't pass any args to cd at all. In this case, it fails. I added a check for that case and updated the function in the post. Let me know if it can be further improved.

    Thanks!

  5. 5 someguy said at 3:02 pm on September 8th, 2009:

    This seems unnecessarily complicated. It's also not safe for pathnames with spaces or other shellcandy. Try:

    function cd () {
    if [ ${1:0:2} == '..' ]; then
    rest=${1:2}
    rest=${rest//./../}
    builtin cd “${1:0:2}/${rest}”
    else
    builtin cd “$1″;
    fi
    }

  6. 6 Jerod Santo said at 3:52 pm on September 8th, 2009:

    You're absolutely right, my function doesn't handle spaces in pathnames at all. I'll give yours a try and if it works as advertised I'll be using it instead, thanks!

    I'm not familiar with:

    ${1:0:2}

    What does that mean?

  7. 7 someguy said at 6:10 pm on September 8th, 2009:

    ${foo:x:y} == foo[x:y] in Python.

  8. 8 Jerod Santo said at 9:03 pm on September 8th, 2009:

    So you're accessing a subset of $1. That makes sense.

    Your function works great in every situation except when you don't pass any args to cd at all. In this case, it fails. I added a check for that case and updated the function in the post. Let me know if it can be further improved.

    Thanks!

blog comments powered by Disqus