cd up, up, and a-up
Posted: September 7th, 2009 | Author: Jerod | Filed under: Tools | View CommentsCommand-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.

*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.
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
}
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?
${foo:x:y} == foo[x:y] in Python.
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!
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
}
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?
${foo:x:y} == foo[x:y] in Python.
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!