<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Orange Splotch &#187; cd</title>
	<atom:link href="http://orangesplotch.com/tags/cd/feed/" rel="self" type="application/rss+xml" />
	<link>http://orangesplotch.com</link>
	<description>Web developing in the middle of the night.</description>
	<lastBuildDate>Sun, 06 Jan 2013 06:30:39 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Bash .. Going Up</title>
		<link>http://orangesplotch.com/bash-going-up/</link>
		<comments>http://orangesplotch.com/bash-going-up/#comments</comments>
		<pubDate>Wed, 17 Nov 2010 08:28:25 +0000</pubDate>
		<dc:creator>mattc</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[bash_aliases]]></category>
		<category><![CDATA[cd]]></category>
		<category><![CDATA[function]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://orangesplotch.com/?p=317</guid>
		<description><![CDATA[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. Here's a little bash function to make traversing directories easier in the command prompt.]]></description>
				<content:encoded><![CDATA[<p>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 '<code>cd ..</code>' command is awkward. Especially when trying to go up several directories. <code>cd ../../../..</code> It's easy to get lost on which directory you are on.</p>
<p>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.</p>
<pre class="code shell bash"># 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&gt; /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
}</pre>
<p>Basically what this function does is allows you to type <code>up X</code> to go up <code>X</code> number of directories. So if I wanted to go up 3 directories, in my bash prompt I would just type <code>up 3</code> instead of <code>cd ../../..</code>.</p>
<p>Additionally, <code>up</code> defaults to going up a single directory. So instead of typing <code>up 1</code> for <code>cd ..</code>, you just have to type <code>up</code>. I've found that I can type <code>up</code> 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.</p>
<p>If you think this might help you out, go ahead and copy that function into your <code>.bash_aliases</code> and enjoy.</p>
<h2>An explanation</h2>
<p>For those of you who aren't content to just copy/paste this function into your <code>.bash_aliases</code>, and actually want to know how it works, here's a breakdown of the code above.</p>
<pre class="code shell bash">COUNTER="$@";
# default $COUNTER to 1 if it isn't already set
if [[ -z $COUNTER ]]; then
	COUNTER=1
fi</pre>
<p>This beginning chunk passes any arguments given to <code>$COUNTER</code>. If there is no argument, then <code>$COUNTER</code> is set to <code>1</code>. <code>-z</code> checks if a variable is set to an empty string (i.e. <code>null</code>).</p>
<pre># make sure $COUNTER is a number
if [ $COUNTER -eq $COUNTER 2&gt; /dev/null ]; then</pre>
<p>This is a great trick I learned from <a href="http://grzechu.blogspot.com/2006/06/bash-scripting-checking-if-variable-is.html">http://grzechu.blogspot.com/2006/06/bash-scripting-checking-if-variable-is.html</a> for checking if a variable is numeric or not. It returns <code>1</code> if <code>$COUNTER</code> is a number and <code>0</code> if it isn't. In the <code>else</code> 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 <code>1</code>. Returning a <code>1</code> in a shell script means something went wrong. Returning a <code>0</code> means the script executed without any problems. If the function gets to the end without any return statements it will default to returning a <code>0</code>.</p>
<p>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.</p>
<pre>nwd=`pwd` # Set new working directory (nwd) to current directory</pre>
<p>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.</p>
<pre># Loop $nwd up directory tree one at a time
until [[ $COUNTER -lt 1 ]]; do
	nwd=`dirname $nwd`
	let COUNTER-=1
done</pre>
<p>The until statement is just another form of a <code>while</code> 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<code> $COUNTER</code> variable is less than <code>1</code>, which would be <code>0</code>.</p>
<p>Each iteration of the loop we set <code>$nwd</code> to the next directory up. We do this by using the <code>dirname</code> command which chops off the last directory in <code>$nwd</code>. The nice thing about <code>dirname</code> is that once you get to the root directory <code>/</code>, it just returns <code>/</code> without throwing any errors. So we don't need to check if <code>$COUNTER</code> is more than the number of directories in our current path. It will just get up to the root directory and stop there.</p>
<p>And of course we need to decrement $COUNTER each iteration.</p>
<pre>cd $nwd # change directories to the new working directory</pre>
<p>Finally we change directories to <code>$nwd</code>. In my original script I changed directories inside the <code>until</code> loop. Instead of setting <code>$nwd</code>, I had a <code>cd ..</code> command. However, doing that meant that I couldn't <code>cd -</code> back to the directory I had started from. Changing the script so that it only does the <code>cd</code> command once meant that <code>cd -</code> still works to get me right back to the original directory. <em>By the way, if you don't know about <code>cd -</code>, it's a very convenient command for jumping back to the directory you were previously in.</em></p>
<p>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.</p>
]]></content:encoded>
			<wfw:commentRss>http://orangesplotch.com/bash-going-up/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
