<?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>i’m so full of ideas &#187; bash</title>
	<atom:link href="http://www.platinumball.net/blog/category/bash/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.platinumball.net/blog</link>
	<description>blog</description>
	<lastBuildDate>Wed, 26 May 2010 17:16:40 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>details</title>
		<link>http://www.platinumball.net/blog/2009/04/09/details/</link>
		<comments>http://www.platinumball.net/blog/2009/04/09/details/#comments</comments>
		<pubDate>Thu, 09 Apr 2009 14:15:19 +0000</pubDate>
		<dc:creator>allen</dc:creator>
				<category><![CDATA[bash]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.platinumball.net/blog/?p=135</guid>
		<description><![CDATA[As of this writing, a google search for &#8220;UIImage rotate&#8221; turns up my previous blog article as the third hit. If you ask me, my take on the subject is far more useful than the top two hits. Yes, I am a shameless braggart, thanks for noticing.
The reason I wanted to rotate UIImages is because [...]]]></description>
			<content:encoded><![CDATA[<p>As of this writing, a google search for &#8220;UIImage rotate&#8221; turns up my previous blog article as the third hit. If you ask me, my take on the subject is far more useful than the top two hits. Yes, I am a shameless braggart, thanks for noticing.</p>
<p>The reason I wanted to rotate UIImages is because I&#8217;m working on an iPhone card game, soon to be revealed. While casting about the &#8216;net for playing card images to use, <a href="http://www.jfitz.com/cards/">I came across this excellent page at www.jfitz.com</a>. There you will find the original Windows-3-era playing card images, made famous by <a href="http://en.wikipedia.org/wiki/Solitaire_(Windows)">Windows Solitaire</a>, everyone&#8217;s favorite time-waster. I can recall whiling away countless hours with that game myself, back when I was a Windows user. One day in the mid nineties I was poking around in my Windows directory and came across <tt>CARDS.DLL</tt>, which I opened up with the resource editor that came with Microsoft&#8217;s compiler of that era, and discovered the bitmaps for all those playing cards lurking inside. I spent ten minutes contemplating writing a Windows card game, then promptly forgot about it. I didn&#8217;t know until recently that those iconic card images were created by the legendary <a href="http://www.kare.com/">Susan Kare</a>, the woman who earlier made the refreshing, tiny black-and-white icons for the original Macintosh. <a href="http://www.folklore.org/StoryView.py?project=Macintosh&#038;story=Steve,_Icon.txt&#038;sortOrder=Sort%20by%20Date&#038;detail=medium&#038;search=susan%20kare">Check out the one she made depicting Steve Jobs</a>. It captures the essence of him in a mere 32 bytes.</p>
<p>Susan Kare&#8217;s Windows playing cards turned out to be perfect for my game. Their dimensions are close to ideal, given the size of the iPhone&#8217;s screen. If they were any bigger, you wouldn&#8217;t be able to fit enough of them onscreen at once. Any smaller and the player would have trouble selecting individual cards with her fingers.</p>
<div class="wp-caption alignright" style="width: 179px"><img class="    " style="margin: 18px;" src="http://www.platinumball.net/png/green_pixel.png" alt="Ugly green pixel" width="169" height="151" /><p class="wp-caption-text">Ugly green pixel</p></div>
<p>I used these graphics for a couple of days and then noticed a problem. The card images all have an unnecessary green pixel in each corner. I originally planned to work around it by using that same shade of green for my background, so that the unwanted pixels would be &#8220;invisible.&#8221; That works okay, sort of, until you draw cards on top of other cards. I refer you now to the picture I&#8217;ve included with this post. Look at that! Ugly green pixel in the midst of an otherwise pristine sea of retro Windows-3-era opulence!</p>
<p>The wise move would be to ignore it. I have more work to do than I can finish in this lifetime. It&#8217;s a minor detail that can wait until <em>after</em> I find out if anybody will ever play this thing. Sadly, this is <em>me</em> we&#8217;re talking about. One thing I don&#8217;t like about myself is my inability to ignore minor junk like this and focus on the bigger picture. But there it was in my head as I was working on this, over and over: ugly green pixels, ugly green pixels.</p>
<p>The proper fix is that the pixels that are now green need to be made transparent. I recently bought a license for <a href="http://flyingmeat.com/acorn/">Acorn</a>, specifically to do programming-related graphics work such as this. Acorn may be capable of making a single pixel transparent, but if so, I can&#8217;t figure out how.</p>
<p>I evaluated other options. Make the green pixels transparent at runtime, just before displaying the images? A quick scan of the docs told me that UIImage doesn&#8217;t make it very easy. Try a different image editor? I downloaded a couple others, which were downright impenetrable, compared to Acorn. I had a look at the docs for <a href="http://www.libpng.org/pub/png/libpng.html">libpng</a>, thinking I might write a one-off utility to transparent-ize the pixels. libpng is a great piece of software, but I quickly determined that it would take me days to figure out the API well enough to do what I want.</p>
<p>You&#8217;re bored so let&#8217;s cut to the chase: the solution was <a href="http://www.imagemagick.org">ImageMagick</a>. I was turned off initially, because it has that faint musty unix smell that makes me fear I&#8217;m in for trouble. I wasn&#8217;t wrong! I tried to install it via <a href="http://www.macports.org/">MacPorts</a>, which gave me a fresh new version of the usual rambling useless error messages it always gives me. Maybe it thought my X11 version was too old? As if I really want to spend all day figuring out if that is in fact what it&#8217;s upset about, or how I would install a later version of X11 that I&#8217;m never going to use. So I downloaded a prebuilt binary distribution from the ImageMagick site, which was, predictably, a pain in the ass to set up. Unix motto: making simple things tedious and unpleasant for four decades!</p>
<p>Have to give them props, though: ImageMagick is a powerful tool. Thirty minutes of poking and prodding later, I devised this bash script to convert my entire folder-full of images at once:</p>
<pre>
<div class="codesnip-container" >
<div class="bash codesnip" style="font-family:monospace;"><span class="co0">#!/bin/sh</span>

<span class="kw1">for</span> <span class="kw2">file</span> <span class="kw1">in</span> $<span class="br0">&#40;</span><span class="kw2">ls</span> <span class="sy0">*</span>.png<span class="br0">&#41;</span>; <span class="kw1">do</span>
&nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&quot;converting <span class="es2">$file</span> ...&quot;</span>
&nbsp; &nbsp; convert <span class="re1">$file</span> <span class="re5">-transparent</span> <span class="st0">&quot;rgb(0,128,0)&quot;</span> <span class="re1">$file</span>
<span class="kw1">done</span></div>
</div>
</pre>
<p>Problem solved. Drawing the new-and-improved images in the iPhone simulator does exactly the right thing. The formerly-green pixels are now invisible. I tried drawing a UIImage directly and also putting it inside an UIImageView, both methods work perfectly.</p>
<p>The practical upshot is that my stupid brain can finally stop fixating on this minor detail, and hopefully I can get back to work.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.platinumball.net/blog/2009/04/09/details/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>bash: timing long-running processes</title>
		<link>http://www.platinumball.net/blog/2009/02/03/bash-timing-long-running-processes/</link>
		<comments>http://www.platinumball.net/blog/2009/02/03/bash-timing-long-running-processes/#comments</comments>
		<pubDate>Tue, 03 Feb 2009 19:44:52 +0000</pubDate>
		<dc:creator>allen</dc:creator>
				<category><![CDATA[bash]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.platinumball.net/blog/?p=67</guid>
		<description><![CDATA[The innertubes have spoken. According to the search terms I&#8217;m seeing in my access logs, you interwebbernauts want to see more bash articles. Very well, then.
Every now and then I write a bash script that might take an hour or more to run. It&#8217;s nice to know exactly how long it took, so you can [...]]]></description>
			<content:encoded><![CDATA[<p>The innertubes have spoken. According to the search terms I&#8217;m seeing in my access logs, you interwebbernauts want to see more bash articles. Very well, then.</p>
<p>Every now and then I write a bash script that might take an hour or more to run. It&#8217;s nice to know exactly how long it took, so you can plan accordingly when you want to run it the next time. So I formalized some bash timing concepts I&#8217;ve been using for years and packaged them up into a code library you can use in your own scripts.</p>
<p>If you&#8217;re just interested in the code, you can skip to the bottom of this entry and cut-and-paste the parts you want into locations of your choosing.  If you&#8217;ve got a minute, I&#8217;ll explain some of the non-obvious bits.</p>
<p>bash functions can only return small integers, typically not larger than 255 or so.  They are intended for use as values you&#8217;d return to the shell, when the script is finished running.  If you want to write a function that returns a string or a large integer, you&#8217;re out of luck.  The way I get around that one is to write functions that use <tt>echo</tt> to print a string to stdout.  The output can be captured by a calling function using this rather awkward syntax:</p>
<p>  &nbsp; &nbsp; <tt>returnValue=$(functionName)</tt></p>
<p>Unfortunately, variables in bash scripts are by default global, and therefore available to all functions. I don&#8217;t like that very much, so my local variable declarations are all prefixed with the keyword <tt>local</tt>, which is supposed to make them visible only within the current function. I have a sneaking suspicion that supposedly local variables can still &#8220;leak&#8221; into other functions, however. I suppose I should investigate that situation and use it as the basis for a future blog post.</p>
<p>Finally, you can use the <tt>source</tt> keyword to pull functions from one script into another, like this:</p>
<p>  &nbsp; &nbsp; <tt>source timerlib.sh</tt></p>
<p>Now, on to the code.  First up is <tt>timerlibtest.sh</tt>, a script that demonstrates use of the timerlib functions.</p>
<pre>
<div class="codesnip-container" >
<div class="bash codesnip" style="font-family:monospace;"><span class="co0">#!/bin/sh</span>

<span class="co0"># timerlibtest.sh -- test for timerlib.sh</span>
<span class="co0"># by allen brunson &nbsp;allen.brunson@gmail.com &nbsp;february 3 2009</span>

<span class="co0"># pull in timerlib functions</span>
<span class="kw3">source</span> timerlib.sh

<span class="co0"># this function shows how to time a long-running process</span>
<span class="kw1">function</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co0"># save current time at the beginning</span>
&nbsp; &nbsp; <span class="kw3">local</span> <span class="kw1">time</span>=$<span class="br0">&#40;</span>timerStart<span class="br0">&#41;</span>
&nbsp; &nbsp; 
&nbsp; &nbsp; <span class="co0"># put whatever you want to time here</span>
&nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&quot;starting long-running process ...&quot;</span>
&nbsp; &nbsp; <span class="kw2">sleep</span> <span class="nu0">2</span>
&nbsp; &nbsp; 
&nbsp; &nbsp; <span class="co0"># display how long it took</span>
&nbsp; &nbsp; timerStop <span class="re1">$time</span> <span class="st0">&quot;elapsed time:&quot;</span>
<span class="br0">&#125;</span>

<span class="co0"># execution start</span>
main <span class="re4">$*</span></div>
</div>
</pre>
<p>Here is the text for <tt>timerlib.sh</tt>:</p>
<pre>
<div class="codesnip-container" >
<div class="bash codesnip" style="font-family:monospace;"><span class="co0">#!/bin/sh</span>

<span class="co0"># timerlib.sh -- functions for timing long-running operations</span>
<span class="co0"># by allen brunson &nbsp;allen.brunson@gmail.com &nbsp;february 3 2009</span>

<span class="co0"># return seconds since 1970</span>
<span class="co0"># does not work on some unix variants. &nbsp;check 'man date' for details</span>

<span class="kw1">function</span> timerCurrent<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw2">date</span> <span class="st0">&quot;+%s&quot;</span>
<span class="br0">&#125;</span>

<span class="co0"># inputs a number of seconds, outputs a string like &quot;2 minutes, 1 second&quot;</span>
<span class="co0"># $1: number of seconds</span>

<span class="kw1">function</span> timerLengthString<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">days</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span>0<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">hour</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span>0<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">mins</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span>0<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">secs</span>=$1
&nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">text</span>=<span class="st0">&quot;&quot;</span>
&nbsp; &nbsp; 
&nbsp; &nbsp; <span class="co0"># convert seconds to days, hours, etc</span>
&nbsp; &nbsp; <span class="re2">days</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span>secs <span class="sy0">/</span> 86400<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="re2">secs</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span>secs <span class="sy0">%</span> 86400<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="re2">hour</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span>secs <span class="sy0">/</span> 3600<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="re2">secs</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span>secs <span class="sy0">%</span> 3600<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="re2">mins</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span>secs <span class="sy0">/</span> 60<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="re2">secs</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span>secs <span class="sy0">%</span> <span class="nu0">60</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; 
&nbsp; &nbsp; <span class="co0"># build full string from unit strings</span>
&nbsp; &nbsp; <span class="re2">text</span>=<span class="st0">&quot;<span class="es2">$text</span><span class="es4">$(timerLengthStringPart $days &quot;day&quot;)</span>&quot;</span>
&nbsp; &nbsp; <span class="re2">text</span>=<span class="st0">&quot;<span class="es2">$text</span><span class="es4">$(timerLengthStringPart $hour &quot;hour&quot;)</span>&quot;</span>
&nbsp; &nbsp; <span class="re2">text</span>=<span class="st0">&quot;<span class="es2">$text</span><span class="es4">$(timerLengthStringPart $mins &quot;minute&quot;)</span>&quot;</span>
&nbsp; &nbsp; <span class="re2">text</span>=<span class="st0">&quot;<span class="es2">$text</span><span class="es4">$(timerLengthStringPart $secs &quot;second&quot;)</span>&quot;</span>
&nbsp; &nbsp; 
&nbsp; &nbsp; <span class="co0"># trim leading and trailing whitespace</span>
&nbsp; &nbsp; <span class="re2">text</span>=<span class="co1">${text## }</span>
&nbsp; &nbsp; <span class="re2">text</span>=<span class="co1">${text%% }</span>
&nbsp; &nbsp; 
&nbsp; &nbsp; <span class="co0"># special case for zero seconds</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#91;</span> <span class="st0">&quot;<span class="es2">$text</span>&quot;</span> == <span class="st0">&quot;&quot;</span> <span class="br0">&#93;</span>; <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re2">text</span>=<span class="st0">&quot;0 seconds&quot;</span>
&nbsp; &nbsp; <span class="kw1">fi</span>
&nbsp; &nbsp; 
&nbsp; &nbsp; <span class="co0"># echo output for the caller</span>
&nbsp; &nbsp; <span class="kw3">echo</span> <span class="co1">${text}</span>
<span class="br0">&#125;</span>

<span class="co0"># formats a time unit into a string</span>
<span class="co0"># $1: integer count of units: 0, 6, etc</span>
<span class="co0"># $2: unit name: &quot;hour&quot;, &quot;minute&quot;, etc</span>

<span class="kw1">function</span> timerLengthStringPart<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">unit</span>=$1
&nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">name</span>=$2
&nbsp; &nbsp; 
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#91;</span> <span class="re1">$unit</span> <span class="re5">-ge</span> 2 <span class="br0">&#93;</span>; <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&quot; <span class="es3">${unit}</span> <span class="es3">${name}</span>s&quot;</span>
&nbsp; &nbsp; <span class="kw1">elif</span> <span class="br0">&#91;</span> <span class="re1">$unit</span> <span class="re5">-ge</span> 1 <span class="br0">&#93;</span>; <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&quot; <span class="es3">${unit}</span> <span class="es3">${name}</span>&quot;</span>
&nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&quot;&quot;</span> &nbsp; &nbsp;
&nbsp; &nbsp; <span class="kw1">fi</span> &nbsp; &nbsp;
<span class="br0">&#125;</span>

<span class="co0"># useful for testing timerLengthString</span>

<span class="kw1">function</span> timerLengthStringTest<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">days</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span>86400<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">hour</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span>3600<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">mins</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span>60<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">secs</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span>1<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; 
&nbsp; &nbsp; timerLengthString &nbsp;0
&nbsp; &nbsp; timerLengthString 20
&nbsp; &nbsp; timerLengthString $<span class="br0">&#40;</span><span class="br0">&#40;</span> <span class="br0">&#40;</span><span class="re1">$hour</span> <span class="sy0">*</span> 3<span class="br0">&#41;</span> + <span class="br0">&#40;</span><span class="re1">$mins</span> <span class="sy0">*</span> 1<span class="br0">&#41;</span> + <span class="br0">&#40;</span><span class="re1">$secs</span> <span class="sy0">*</span> 52<span class="br0">&#41;</span> <span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; timerLengthString $<span class="br0">&#40;</span><span class="br0">&#40;</span> <span class="br0">&#40;</span><span class="re1">$days</span> <span class="sy0">*</span> 1<span class="br0">&#41;</span> + <span class="br0">&#40;</span><span class="re1">$secs</span> <span class="sy0">*</span> <span class="nu0">14</span><span class="br0">&#41;</span> <span class="br0">&#41;</span><span class="br0">&#41;</span>
<span class="br0">&#125;</span>

<span class="co0"># synonym for timerCurrent</span>

<span class="kw1">function</span> timerStart<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; timerCurrent <span class="re4">$*</span>
<span class="br0">&#125;</span>

<span class="co0"># display final elapsed time</span>
<span class="co0"># $1: value returned from an earlier call to timerStart()</span>
<span class="co0"># $2: optional descriptive string, such as &quot;total wait time:&quot;</span>

<span class="kw1">function</span> timerStop<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">desc</span>=$2
&nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">secs</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span>0<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">stop</span>=$<span class="br0">&#40;</span>timerCurrent<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">text</span>=<span class="st0">&quot;&quot;</span>
&nbsp; &nbsp; <span class="kw3">local</span> <span class="kw1">time</span>=$1
&nbsp; &nbsp; 
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#91;</span> <span class="st0">&quot;<span class="es2">$desc</span>&quot;</span> <span class="sy0">!</span>= <span class="st0">&quot;&quot;</span> <span class="br0">&#93;</span>; <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re2">text</span>=<span class="st0">&quot;<span class="es2">$desc</span> &quot;</span>
&nbsp; &nbsp; <span class="kw1">fi</span>
&nbsp; &nbsp; 
&nbsp; &nbsp; <span class="re2">secs</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span> <span class="re1">$stop</span> - <span class="re1">$time</span> <span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="re2">text</span>=<span class="st0">&quot;<span class="es2">$text</span><span class="es4">$(timerLengthString $secs)</span>&quot;</span>
&nbsp; &nbsp; 
&nbsp; &nbsp; <span class="kw3">echo</span> <span class="re1">$text</span>
<span class="br0">&#125;</span></div>
</div>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.platinumball.net/blog/2009/02/03/bash-timing-long-running-processes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>bash scripts: glue for unix</title>
		<link>http://www.platinumball.net/blog/2009/01/16/bash-scripts-glue-for-unix/</link>
		<comments>http://www.platinumball.net/blog/2009/01/16/bash-scripts-glue-for-unix/#comments</comments>
		<pubDate>Fri, 16 Jan 2009 23:01:14 +0000</pubDate>
		<dc:creator>allen</dc:creator>
				<category><![CDATA[bash]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.platinumball.net/blog/?p=31</guid>
		<description><![CDATA[At my last full-time job, I wrote some hideously complex bash scripts. They started out small and kind of got away from me. In hindsight, that&#8217;s pretty much the way it had to be. I was in charge of dozens of linux computers running hundreds of programs that I wrote, interacting with each other in [...]]]></description>
			<content:encoded><![CDATA[<p>At my last full-time job, I wrote some hideously complex bash scripts. They started out small and kind of got away from me. In hindsight, that&#8217;s pretty much the way it had to be. I was in charge of dozens of linux computers running hundreds of programs that I wrote, interacting with each other in complex ways. I didn&#8217;t fully understand the problem space, and even if I had, I didn&#8217;t have time to write all that logic in a more formal language. bash scripts are the perfect medium for spitballing solutions to problems you&#8217;re kind of fuzzy about.</p>
<p>This was my first attempt to solve big problems with bash, so I had a lot to learn. For example, I was surprised to discover that this script doesn&#8217;t work:</p>
<pre>
<div class="codesnip-container" >
<div class="bash codesnip" style="font-family:monospace;"><span class="co0">#!/bin/sh</span>

function_test

<span class="kw1">function</span> function_test<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
    <span class="kw3">echo</span> <span class="st0">&quot;test&quot;</span>
<span class="br0">&#125;</span></div>
</div>
</pre>
<p>This is an attempt to call a function before it&#8217;s defined. Trivial in C++, my native language, but not allowed in bash.</p>
<p>I&#8217;m kind of embarrassed to admit that I struggled with this for a long time. I wrote more and more bash functions, which became increasingly interdependent, so this problem got more troublesome as time went on.</p>
<p>For this reason and many others, I decided to adopt a more C-like structure for my bash scripts. Like this:</p>
<pre>
<div class="codesnip-container" >
<div class="bash codesnip" style="font-family:monospace;"><span class="co0">#!/bin/sh</span>

<span class="kw1">function</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
    test1
    test2
<span class="br0">&#125;</span>

<span class="kw1">function</span> test1<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
    <span class="kw3">echo</span> <span class="st0">&quot;test1&quot;</span>
<span class="br0">&#125;</span>

<span class="kw1">function</span> test2<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
    <span class="kw3">echo</span> <span class="st0">&quot;test2&quot;</span>
<span class="br0">&#125;</span>

main <span class="re4">$*</span></div>
</div>
</pre>
<p><tt>main()</tt> is calling <tt>test1()</tt> and <tt>test2()</tt> before they are defined.  But it doesn&#8217;t matter anymore, because <em>all</em> functions are defined before the program starts running. The bash interpreter has read the entire script before execution begins at the very last line, when <tt>main()</tt> is called.</p>
<p>I would have done this right from the beginning, but I didn&#8217;t know about the <tt>$*</tt> trick. That passes all command-line parameters received by the script to the <tt>main()</tt> function, so it can do whatever it likes with them.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.platinumball.net/blog/2009/01/16/bash-scripts-glue-for-unix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
