I've been doing a lot of work in the bash shell lately and thought I'd share one of the hacks that makes life just a little easier. For me, the 'cd ..' command is awkward. Especially when trying to go up several directories. cd ../../../.. It's easy to get lost on which directory you are on.
I tried looking for a better way online, but couldn't find anything. Because of this, I came up with my own little bash function. And here it is, copied directly from my .bash_aliases file.
# Go up directory tree X number of directories
function up() {
COUNTER="$@";
# default $COUNTER to 1 if it isn't already set
if [[ -z $COUNTER ]]; then
COUNTER=1
fi
# make sure $COUNTER is a number
if [ $COUNTER -eq $COUNTER 2> /dev/null ]; then
nwd=`pwd` # Set new working directory (nwd) to current directory
# Loop $nwd up directory tree one at a time
until [[ $COUNTER -lt 1 ]]; do
nwd=`dirname $nwd`
let COUNTER-=1
done
cd $nwd # change directories to the new working directory
else
# print usage and return error
echo "usage: up [NUMBER]"
return 1
fi
}
Basically what this function does is allows you to type up X to go up X number of directories. So if I wanted to go up 3 directories, in my bash prompt I would just type up 3 instead of cd ../../...
Additionally, up defaults to going up a single directory. So instead of typing up 1 for cd .., you just have to type up. I've found that I can type up a lot faster than hitting the '.' key twice. For all the time I spend in the bash command prompt, little improvements like this go a long way.
If you think this might help you out, go ahead and copy that function into your .bash_aliases and enjoy.
An explanation
For those of you who aren't content to just copy/paste this function into your .bash_aliases, and actually want to know how it works, here's a breakdown of the code above.
COUNTER="$@"; # default $COUNTER to 1 if it isn't already set if [[ -z $COUNTER ]]; then COUNTER=1 fi
This beginning chunk passes any arguments given to $COUNTER. If there is no argument, then $COUNTER is set to 1. -z checks if a variable is set to an empty string (i.e. null).
# make sure $COUNTER is a number if [ $COUNTER -eq $COUNTER 2> /dev/null ]; then
This is a great trick I learned from http://grzechu.blogspot.com/2006/06/bash-scripting-checking-if-variable-is.html for checking if a variable is numeric or not. It returns 1 if $COUNTER is a number and 0 if it isn't. In the else block, at the bottom of the script, I have it print a usage statement telling them to provide a number and then I return a 1. Returning a 1 in a shell script means something went wrong. Returning a 0 means the script executed without any problems. If the function gets to the end without any return statements it will default to returning a 0.
So all of that code is for getting the input, setting it to a default and doing some basic error checking. Now onto the meat of this bash function.
nwd=`pwd` # Set new working directory (nwd) to current directory
I think the comment on this line make it pretty clear what we're doing. This is our starting directory and we are going to go up from here.
# Loop $nwd up directory tree one at a time until [[ $COUNTER -lt 1 ]]; do nwd=`dirname $nwd` let COUNTER-=1 done
The until statement is just another form of a while loop in bash. Only it loops while the statement is false instead of while it is true, i.e. "until" the statement becomes true. So here we are looping until our $COUNTER variable is less than 1, which would be 0.
Each iteration of the loop we set $nwd to the next directory up. We do this by using the dirname command which chops off the last directory in $nwd. The nice thing about dirname is that once you get to the root directory /, it just returns / without throwing any errors. So we don't need to check if $COUNTER is more than the number of directories in our current path. It will just get up to the root directory and stop there.
And of course we need to decrement $COUNTER each iteration.
cd $nwd # change directories to the new working directory
Finally we change directories to $nwd. In my original script I changed directories inside the until loop. Instead of setting $nwd, I had a cd .. command. However, doing that meant that I couldn't cd - back to the directory I had started from. Changing the script so that it only does the cd command once meant that cd - still works to get me right back to the original directory. By the way, if you don't know about cd -, it's a very convenient command for jumping back to the directory you were previously in.
If you have any questions about this function, or see ways to improve it, please let me know. I may be reinventing the wheel here, but I couldn't find anything online to add this functionality so I thought I'd post my own solution. If you know of a better way to do this, please post it in the comments.