<?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>JAW Speak &#187; automation</title>
	<atom:link href="http://jawspeak.com/category/automation/feed/" rel="self" type="application/rss+xml" />
	<link>http://jawspeak.com</link>
	<description>Jonathan Andrew Wolter</description>
	<lastBuildDate>Sun, 13 May 2012 19:45:14 +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>Subversion Parallel Multi-Branch Development And Merging</title>
		<link>http://jawspeak.com/2010/11/03/subversion-parallel-multi-branch-development-and-merging/</link>
		<comments>http://jawspeak.com/2010/11/03/subversion-parallel-multi-branch-development-and-merging/#comments</comments>
		<pubDate>Wed, 03 Nov 2010 09:21:20 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[automation]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[thoughtworks]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[trunk based development]]></category>

		<guid isPermaLink="false">http://jawspeak.com/?p=148</guid>
		<description><![CDATA[Reading time: 2 &#8211; 2 minutes

			
				
			
		
As discussed in my previous post, I dislike merging-based-development, preferring Trunk Based Development instead. But, sometimes you&#8217;re stuck with a long-lived development branch, and you need to merge changes (subversion tree-conflicts and all). At the end of the post, I have several scripts I used to make this easier. Not [...]]]></description>
			<content:encoded><![CDATA[<p>Reading time: 2 &#8211; 2 minutes</p>
<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fjawspeak.com%2F2010%2F11%2F03%2Fsubversion-parallel-multi-branch-development-and-merging%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=?url=http%3A%2F%2Fjawspeak.com%2F2010%2F11%2F03%2Fsubversion-parallel-multi-branch-development-and-merging%2F&amp;style=normal&amp;service=bit.ly" height="61" width="51" /><br />
			</a>
		</div>
<p>As discussed in my previous post, I <a href="http://jawspeak.com/2009/09/17/how-to-do-3-way-merges-with-subversion-and-kdiff3/">dislike merging-based-development</a>, preferring Trunk Based Development instead. But, sometimes you&#8217;re stuck with a long-lived development branch, and you need to merge changes (subversion tree-conflicts and all). At the end of the post, I have several scripts I used to make this easier. Not the prettiest, but saved a lot of pain when we had major refactorings in trunk, and needed to locate and merge the changes to those files in a long lived (read: horrible) dev branch.</p>
<p>Imagine this scenario: Multiple streams of development, with a long-lived &#8220;3.0 dev&#8221; branch that has never reintegrated with the trunk. (Because 3.0 has new features that won&#8217;t go into production for many months).</p>
<p><a title="branch-and-merge-problems-1 by JAWspeak, on Flickr" href="http://www.flickr.com/photos/jawspeak/5153278909/"><img src="http://farm2.static.flickr.com/1361/5153278909_13cde87ca6.jpg" alt="branch-and-merge-problems-1" width="500" height="287" /></a></p>
<p>There are substantial dangers in this approach. This diagram only touches on the surface of the areas of risk in which a merge could fail. Solution? Trunk based development / branch by abstraction.</p>
<p><a title="branch-and-merge-problems-2 by JAWspeak, on Flickr" href="http://www.flickr.com/photos/jawspeak/5153884916/"><img src="http://farm2.static.flickr.com/1135/5153884916_23acf12aee.jpg" alt="branch-and-merge-problems-2" width="500" height="275" /></a></p>
<p>Given this required scenario, I developed a few best practices and scripts for merging. The best practices involved having multiple branches checked out into different directories. And then  we would find equivalent files that have moved and merge the  tree-conflicts.</p>
<p>Scripts to assist in Subversion 3 way merging.</p>
<p><script src="http://gist.github.com/188820.js"></script> Custom <code>diff3-cmd</code> configuration setting in svn: <script src="https://gist.github.com/188824.js"> </script></p>
]]></content:encoded>
			<wfw:commentRss>http://jawspeak.com/2010/11/03/subversion-parallel-multi-branch-development-and-merging/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Less Hate with Maven Part 2: The Wrapper Script</title>
		<link>http://jawspeak.com/2010/05/28/less-hate-with-maven-part-2-the-wrapper-script/</link>
		<comments>http://jawspeak.com/2010/05/28/less-hate-with-maven-part-2-the-wrapper-script/#comments</comments>
		<pubDate>Fri, 28 May 2010 14:03:04 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[automation]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[thoughtworks]]></category>
		<category><![CDATA[maven]]></category>

		<guid isPermaLink="false">http://jawspeak.com/?p=223</guid>
		<description><![CDATA[Reading time: < 1 minute

			
				
			
		
I previously wrote about useful debugging techniques with maven. Our maven builds have become complex, with Branch By Abstraction, and about 40 devs working simultaneously on the codebase in 2 continents. We have at least 3 profiles for each of the branch abstractions that are currently running in the codebase. I&#8217;m [...]]]></description>
			<content:encoded><![CDATA[<p>Reading time: < 1 minute</p>
<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fjawspeak.com%2F2010%2F05%2F28%2Fless-hate-with-maven-part-2-the-wrapper-script%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=?url=http%3A%2F%2Fjawspeak.com%2F2010%2F05%2F28%2Fless-hate-with-maven-part-2-the-wrapper-script%2F&amp;style=normal&amp;service=bit.ly" height="61" width="51" /><br />
			</a>
		</div>
<p>I previously wrote about <a href="http://jawspeak.com/2010/05/14/12-tips-for-less-hate-of-maven/">useful debugging techniques with maven</a>. Our maven builds have become complex, with <a href="http://paulhammant.com/blog/branch_by_abstraction.html">Branch By Abstraction</a>, and about 40 devs working simultaneously on the codebase in 2 continents. We have at least 3 profiles for each of the branch abstractions that are currently running in the codebase. I&#8217;m one of the tech leads, and in order to keep the team&#8217;s build consistent and easy to remember, we have a wrapper script (thanks to <a href="http://offbytwo.com">Cosmin</a>).</p>
<p>Here it is:</p>
<p><script src="http://gist.github.com/401376.js?file=make.sh"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://jawspeak.com/2010/05/28/less-hate-with-maven-part-2-the-wrapper-script/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>maven + growlnotify for notification when your build finishes</title>
		<link>http://jawspeak.com/2009/12/31/maven-growlnotify-for-notification-when-your-build-finishes/</link>
		<comments>http://jawspeak.com/2009/12/31/maven-growlnotify-for-notification-when-your-build-finishes/#comments</comments>
		<pubDate>Thu, 31 Dec 2009 18:23:12 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[automation]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[maven]]></category>

		<guid isPermaLink="false">http://jawspeak.com/?p=154</guid>
		<description><![CDATA[Reading time: 1 &#8211; 2 minutes

			
				
			
		
Working on os x with Spaces means I want to read something on another space instead of waiting idly for a 50 second build. But, I don&#8217;t want to get distracted. So, I use Growl and growlnotify for notifications of the build&#8217;s completion.
#!/bin/sh
# this file is called: mvn (and is [...]]]></description>
			<content:encoded><![CDATA[<p>Reading time: 1 &#8211; 2 minutes</p>
<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fjawspeak.com%2F2009%2F12%2F31%2Fmaven-growlnotify-for-notification-when-your-build-finishes%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=?url=http%3A%2F%2Fjawspeak.com%2F2009%2F12%2F31%2Fmaven-growlnotify-for-notification-when-your-build-finishes%2F&amp;style=normal&amp;service=bit.ly" height="61" width="51" /><br />
			</a>
		</div>
<p>Working on os x with Spaces means I want to read something on another space instead of waiting idly for a 50 second build. But, I don&#8217;t want to get distracted. So, I use <a href="http://growl.info/">Growl</a> and <a href="http://growl.info/documentation/growlnotify.php">growlnotify</a> for notifications of the build&#8217;s completion.</p>
<pre>#!/bin/sh
# this file is called: mvn (and is executable, and added to path before actual mvn command)

# capture all args passed in to forward to real mvn
ARGS=$*

# We need the client's specific settings.xml, so always specify it now
/usr/bin/mvn -s /Volumes/TrueCryptClient/opt/maven/conf/settings.xml $ARGS 

# when you have growlnotify installed and on your path, this will pop it up
# when the build is done
growlnotify -m "DONE: maven $ARGS"
</pre>
<p>Note: if you get this error from growlnotify: <tt>could not find local GrowlApplicationBridgePathway, falling back to NSDNC</tt>, it probably means growl is not started. Start up growl in your System Preferences.</p>
<p><strong>Update:</strong> Thanks Cosmin, for the enhancement. Use this snipped in the script. Have an environmental variable for what the notify command is. And say what the build status is in the growl notify.:</p>
<pre>if [[ -n $NOTIFY ]]; then
    ($command &amp;&amp; $NOTIFY "Build Complete" &amp;&amp; exit 0) || ($NOTIFY "Build Failed" &amp;&amp; exit 127)
else
    $command
fi
</pre>
]]></content:encoded>
			<wfw:commentRss>http://jawspeak.com/2009/12/31/maven-growlnotify-for-notification-when-your-build-finishes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to do 3-way merges with Subversion and Kdiff3</title>
		<link>http://jawspeak.com/2009/09/17/how-to-do-3-way-merges-with-subversion-and-kdiff3/</link>
		<comments>http://jawspeak.com/2009/09/17/how-to-do-3-way-merges-with-subversion-and-kdiff3/#comments</comments>
		<pubDate>Fri, 18 Sep 2009 01:49:37 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[automation]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[trunk based development]]></category>

		<guid isPermaLink="false">http://jawspeak.com/?p=140</guid>
		<description><![CDATA[Reading time: 4 &#8211; 7 minutes

			
				
			
		
I do not endorse branch based development. I prefer trunk based development. Specifically I like what my colleague Paul calls Branch By Abstraction, coined by Stacy Curl, and recently mentioned by Martin Fowler (All one time ThoughtWorkers, and 2 currently).
If you&#8217;re stuck with merging though, 3-way merges make it much [...]]]></description>
			<content:encoded><![CDATA[<p>Reading time: 4 &#8211; 7 minutes</p>
<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fjawspeak.com%2F2009%2F09%2F17%2Fhow-to-do-3-way-merges-with-subversion-and-kdiff3%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=?url=http%3A%2F%2Fjawspeak.com%2F2009%2F09%2F17%2Fhow-to-do-3-way-merges-with-subversion-and-kdiff3%2F&amp;style=normal&amp;service=bit.ly" height="61" width="51" /><br />
			</a>
		</div>
<p>I do not endorse branch based development. I prefer trunk based development. Specifically I like what my colleague Paul calls <a href="http://paulhammant.com/blog/branch_by_abstraction.html">Branch By Abstraction</a>, coined by <a href="http://digital-compulsion.blogspot.com/2007/04/branching-by-abstraction.html">Stacy Curl</a>, and recently mentioned by <a href="http://martinfowler.com/bliki/FeatureBranch.html">Martin Fowler</a> (All one time <a href="http://ThoughtWorks.com">ThoughtWorkers</a>, and 2 currently).</p>
<p>If you&#8217;re stuck with merging though, 3-way merges make it much easier. Doing it with subversion is easy. Instructions are for Linux.</p>
<ol>
<li>apt-get or yum install kdiff3.</li>
<li>Edit your <tt>/etc/subversion/config</tt> and fin the line with <tt>diff3-cmd</tt>, set it to: <tt>diff3-cmd=/usr/local/bin/svndiff.sh</tt></li>
<li>Next, create the file <tt>/usr/local/bin/svndiff.sh</tt>. See below for the script you&#8217;ll want to enter in it.</li>
</ol>
<p>Now when you get a merge conflict you will choose <tt>M</tt> and merge will open in kdiff3. On the left is the base revision, in the middle is your working copy, and on the right the incoming change. This is a little more to look at, but it is invaluable when dealing with merges. I wouldn&#8217;t go back to 2 way diff ever again.</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">#!/bin/bash
&nbsp;
# tim/paul: this is a copy of the file located at http://www.yolinux.com/TUTORIALS/src/svndiffwrapper.txt
#    modified to do a non-conflicting merge automatically. see #HERE#
&nbsp;
# Return an errorcode of 0 on successful merge, 1 if unresolved conflicts
# remain in the result.  Any other errorcode will be treated as fatal.
# Author: Michael Bradley
&nbsp;
#NOTE: all output must be redirected to stderr with &quot;1&amp;gt;&amp;amp;2&quot; as all stdout output is written to the output file
&nbsp;
VDIFF3=&quot;kdiff3&quot;
DIFF3=&quot;diff3&quot;
DIFF=&quot;kdiff3&quot;  
&nbsp;
promptUser ()
{
    read answer
    case &quot;${answer}&quot; in
&nbsp;
        &quot;M&quot;         )
        echo &quot;&quot; 1&amp;gt;&amp;amp;2
        echo &quot;Attempting to merge ${baseFileName} with ${DIFF}&quot; 1&amp;gt;&amp;amp;2
        $VDIFF3 $older $mine $theirs --L1 $labelOlder --L2 $labelMine --L3 $labelTheirs -o $output 1&amp;gt;&amp;amp;2
        bLoop=1
        if [ -f $output ]; then
            if [ -s $output ]; then
                #output succesfully written
                bLoop=0
            fi
        fi
        if [ $bLoop = 0 ]; then
            cat $output
            rm -f $output
            exit 0
        else
            echo &quot;Merge failed, try again&quot; 1&amp;gt;&amp;amp;2
        fi
&nbsp;
        ;;
&nbsp;
        &quot;m&quot;         )
        echo &quot;&quot; 1&amp;gt;&amp;amp;2
        echo &quot;Attempting to auto-merge ${baseFileName}&quot; 1&amp;gt;&amp;amp;2
        diff3 -L $labelMine -L $labelOlder -L $labelTheirs -Em $mine $older $theirs &amp;gt; $output
        if [ $? = 1 ]; then
            #Can't auto merge
            rm -f $output
            $VDIFF3 $older $mine $theirs --L1 $labelOlder --L2 $labelMine --L3 $labelTheirs -o $output --auto 1&amp;gt;&amp;amp;2
            bLoop=1
            if [ -f $output ]; then
                if [ -s $output ]; then
                    #output succesfully written
                    bLoop=0
                fi
            fi
            if [ $bLoop = 0 ]; then
                cat $output
                rm -f $output
                exit 0
            else
                echo &quot;Merge failed, try again&quot; 1&amp;gt;&amp;amp;2
            fi
        else
            #We can automerge, and we already did it
            cat $output
            rm -f $output
            exit 0
        fi
        ;;
&nbsp;
        &quot;diff3&quot; | &quot;Diff3&quot; | &quot;DIFF3&quot;  )
        echo &quot;&quot; 1&amp;gt;&amp;amp;2
        echo &quot;Diffing...&quot; 1&amp;gt;&amp;amp;2
        $VDIFF3 $older $mine $theirs --L1 $labelOlder --L2 $labelMine --L3 $labelTheirs 1&amp;gt;&amp;amp;2
        ;;
&nbsp;
        &quot;diff&quot; | &quot;Diff&quot; | &quot;DIFF&quot;  )
        echo &quot;&quot; 1&amp;gt;&amp;amp;2
        echo &quot;Diffing...&quot; 1&amp;gt;&amp;amp;2
        $DIFF $mine $theirs -L $labelMine -L $labelTheirs 1&amp;gt;&amp;amp;2
        ;;
&nbsp;
        &quot;A&quot; | &quot;a&quot;   )
        echo &quot;&quot; 1&amp;gt;&amp;amp;2
        echo &quot;Accepting remote version of file...&quot; 1&amp;gt;&amp;amp;2
        cat ${theirs}
        exit 0
        ;;
&nbsp;
        &quot;I&quot; | &quot;i&quot;   )
        echo &quot;&quot; 1&amp;gt;&amp;amp;2
        echo &quot;Keeping local modifications...&quot; 1&amp;gt;&amp;amp;2
        cat ${mine}
        exit 0
        ;;
&nbsp;
        &quot;R&quot; | &quot;r&quot;   )
        echo &quot;&quot; 1&amp;gt;&amp;amp;2
        echo &quot;Reverting to base...&quot; 1&amp;gt;&amp;amp;2
        cat ${older}
        exit 0
        ;;
&nbsp;
        &quot;D&quot; | &quot;d&quot;   )
        echo &quot;&quot; 1&amp;gt;&amp;amp;2
        echo &quot;Runnig diff3...&quot; 1&amp;gt;&amp;amp;2
        diff3 -L $labelMine -L $labelOlder -L $labelTheirs -Em $mine $older $theirs
        #Exit with return vaule of the diff3 (to write out files if necessary)
        exit $?
        ;;
&nbsp;
        &quot;S&quot; | &quot;s&quot;   )
        echo &quot;&quot; 1&amp;gt;&amp;amp;2
        echo &quot;Saving for later...&quot; 1&amp;gt;&amp;amp;2
        cat ${mine}
        #Exit with return vaule of 1 to force writting of files
        exit 1
        ;;
&nbsp;
        &quot;Fail&quot; | &quot;fail&quot; | &quot;FAIL&quot;   )
        echo &quot;&quot; 1&amp;gt;&amp;amp;2
        echo &quot;Failing...&quot; 1&amp;gt;&amp;amp;2
        exit 2
        ;;
&nbsp;
        &quot;H&quot; | &quot;h&quot;   )
        echo &quot;&quot; 1&amp;gt;&amp;amp;2
        echo &quot;USAGE OPTIONS:&quot; 1&amp;gt;&amp;amp;2
        echo &quot;  [A]ccept    Accept $labelTheirs and throw out local modifications&quot; 1&amp;gt;&amp;amp;2
        echo &quot;  [D]efault   Use diff3 to merge files (same behavior as vanilla SVN)&quot; 1&amp;gt;&amp;amp;2
        echo &quot;  [Fail]      Kills the command (not suggested)&quot; 1&amp;gt;&amp;amp;2
        echo &quot;  [H]elp      Print this message&quot; 1&amp;gt;&amp;amp;2
        echo &quot;  [I]gnore    Keep your locally modified version as is&quot; 1&amp;gt;&amp;amp;2
        echo &quot;  [M]erge     Manually merge using ${VDIFF3}&quot; 1&amp;gt;&amp;amp;2
        echo &quot;  [m]erge     Same as &quot;M&quot; but attempts to automerge if possible&quot; 1&amp;gt;&amp;amp;2
        echo &quot;  [R]evert    Revert to base version (${labelOlder})&quot; 1&amp;gt;&amp;amp;2
        echo &quot;  [S]ave      Same as 'I' but writes out rold, rnew, and rmine files to deal with later&quot; 1&amp;gt;&amp;amp;2
        echo &quot;  [diff]      Type 'diff' to diff versions $labelMine and $labelTheirsthe before making a descision&quot; 1&amp;gt;&amp;amp;2
        echo &quot;  [diff3]     Type 'diff3' to diff all three versions before making a descision&quot; 1&amp;gt;&amp;amp;2
        echo &quot;&quot; 1&amp;gt;&amp;amp;2
        ;;
&nbsp;
        *   )
        echo &quot;'${answer}' is not an option, try again.&quot; 1&amp;gt;&amp;amp;2
        ;;
    esac
}
&nbsp;
if [ -z $2 ]
then
    echo ERROR: This script expects to be called by subversion
    exit 1
fi
&nbsp;
if [ $2 = &quot;-m&quot; ]
then
    #Setup vars
    labelMine=${4}
    labelOlder=${6}
    labelTheirs=${8}
    mine=${9}
    older=${10}
    theirs=${11}
    output=${9}.svnDiff3TempOutput
    baseFileName=`echo $mine | sed -e &quot;s/.tmp$//&quot;`
&nbsp;
#HERE#
    diff3 -L $labelMine -L $labelOlder -L $labelTheirs -Em $mine $older $theirs &amp;gt; $output
    if [ $? = 1 ]; then
        #Can't auto merge
        #Prompt user for direction
        while [ 1 ]
        do
            echo &quot;&quot; 1&amp;gt;&amp;amp;2
            echo &quot;${baseFileName} requires merging.&quot; 1&amp;gt;&amp;amp;2
            echo &quot;&quot; 1&amp;gt;&amp;amp;2
            echo &quot;What would you like to do?&quot; 1&amp;gt;&amp;amp;2
            echo &quot;[M]erge [A]ccept [I]gnore [R]evert [D]efault [H]elp&quot; 1&amp;gt;&amp;amp;2
            promptUser
        done
    else
        #We can automerge, and we already did it
        cat $output
        rm -f $output
        exit 0
    fi
else
    L=&quot;-L&quot;         #Argument option for left label
    R=&quot;-L&quot;         #Argument option for right label
    label1=$3       #Left label
    label2=$5       #Right label
    file1=$6        #Left file
    file2=$7        #Right file
&nbsp;
    $DIFF $file1 $file2 $L &quot;$label1&quot; $L &quot;$label2&quot; &amp;amp;
    #$DIFF $file1 $file2 &amp;amp;
    #wait for the command to finish
    wait
fi
exit 0</pre></div></div>

<p>Note: I also posted this to a gist on github: <a href="http://gist.github.com/188824">svndiff.sh</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://jawspeak.com/2009/09/17/how-to-do-3-way-merges-with-subversion-and-kdiff3/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Ruby Script to Organize Mp3&#8217;s based on ID3 Genre Tag</title>
		<link>http://jawspeak.com/2009/09/05/ruby-script-to-organize-mp3s-based-on-id3-genre-tag/</link>
		<comments>http://jawspeak.com/2009/09/05/ruby-script-to-organize-mp3s-based-on-id3-genre-tag/#comments</comments>
		<pubDate>Sun, 06 Sep 2009 00:06:57 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[automation]]></category>
		<category><![CDATA[music]]></category>

		<guid isPermaLink="false">http://jawspeak.com/?p=136</guid>
		<description><![CDATA[Reading time: 2 &#8211; 4 minutes

			
				
			
		
I had one gigantic directory of all my tagged and organized mp3 files. Problem is it was too big to use. This bloated my library and I have since not been able to fit my music on my laptop. I needed to manipulate mp3 files by genre and extract them [...]]]></description>
			<content:encoded><![CDATA[<p>Reading time: 2 &#8211; 4 minutes</p>
<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fjawspeak.com%2F2009%2F09%2F05%2Fruby-script-to-organize-mp3s-based-on-id3-genre-tag%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=?url=http%3A%2F%2Fjawspeak.com%2F2009%2F09%2F05%2Fruby-script-to-organize-mp3s-based-on-id3-genre-tag%2F&amp;style=normal&amp;service=bit.ly" height="61" width="51" /><br />
			</a>
		</div>
<p>I had one gigantic directory of all my tagged and organized mp3 files. Problem is it was too big to use. This bloated my library and I have since not been able to fit my music on my laptop. I needed to manipulate mp3 files by genre and extract them out of this single directory to create smaller libraries. I spent all of about two minutes looking for a program to do this before deciding to write a script. Truthfully, it was worse: once upon a time I over-enthusiastically downloaded <a href="http://www.stepmania.com/">StepMania</a> and 493 DDR games/songs. And then, I added all the songs into my music library. It&#8217;s a great party game, but not the kind of music I want to listen to.</p>
<p>Many <a href="http://www.id3.org/Implementations">implementations</a> exist for reading <a href="http://en.wikipedia.org/wiki/ID3">ID3</a> tags. I first tried <a href="http://ruby-mp3info.rubyforge.org/">ruby-mp3info</a>, however it didn&#8217;t read my custom genre (&#8216;DDR&#8217;) so then I moved to <a href="http://id3lib-ruby.rubyforge.org/">id3lib-ruby</a> which uses the c++ <a href="http://id3lib.sourceforge.net/">id3lib</a> library.</p>
<p>This worked like a charm. I ran the script over all my directories and built up a list of the directories.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;">#!/usr/bin/env ruby</span>
<span style="color:#008000; font-style:italic;"># find_music.sh</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;rubygems&quot;</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'id3lib'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'find'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'set'</span>
&nbsp;
ddr_files = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
ddr_dirs = <span style="color:#CC00FF; font-weight:bold;">Set</span>.<span style="color:#9900CC;">new</span>
&nbsp;
search_dir = <span style="color:#996600;">'~/media/music/music_categorized'</span>
&nbsp;
<span style="color:#CC00FF; font-weight:bold;">Find</span>.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span>search_dir<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>file<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#9966CC; font-weight:bold;">next</span> <span style="color:#9966CC; font-weight:bold;">if</span> file !~ <span style="color:#006600; font-weight:bold;">/</span>.<span style="color:#006600; font-weight:bold;">*</span>mp3$<span style="color:#006600; font-weight:bold;">/</span>
  mp3 = <span style="color:#6666ff; font-weight:bold;">ID3Lib::Tag</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>file<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">next</span> <span style="color:#9966CC; font-weight:bold;">if</span> mp3.<span style="color:#9900CC;">genre</span> != <span style="color:#996600;">'DDR'</span>
  ddr_dirs <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">dirname</span><span style="color:#006600; font-weight:bold;">&#40;</span>file<span style="color:#006600; font-weight:bold;">&#41;</span>
  ddr_files <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> file   <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;%s, %s --&gt; AT: %s&quot;</span> <span style="color:#006600; font-weight:bold;">%</span> <span style="color:#006600; font-weight:bold;">&#91;</span>mp3.<span style="color:#9900CC;">genre</span>, mp3.<span style="color:#9900CC;">album</span>, file<span style="color:#006600; font-weight:bold;">&#93;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'result-ddr-files.txt'</span>, <span style="color:#996600;">'w'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span>
  f.<span style="color:#9900CC;">write</span><span style="color:#006600; font-weight:bold;">&#40;</span>ddr_files.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;<span style="color:#000099;">\n</span>&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'result-ddr-dirs.txt'</span>, <span style="color:#996600;">'w'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span>
  ddr_dirs.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>d<span style="color:#006600; font-weight:bold;">|</span> f.<span style="color:#9900CC;">write</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;%s<span style="color:#000099;">\n</span>&quot;</span> <span style="color:#006600; font-weight:bold;">%</span> d<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Next I reviewed the two output files, then ran the file <tt>result-ddr-dirs.txt</tt> in as an argument into this next script. That removed almost a gig of music from my library.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;">#!/usr/bin/env ruby</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span>ARGV.<span style="color:#9900CC;">length</span> != <span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;Usage: #{__FILE__} input_file&quot;</span>
  <span style="color:#CC0066; font-weight:bold;">exit</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
destination=<span style="color:#996600;">&quot;/home/jwolter/media/music/music_ddr_questionable_value/&quot;</span>
&nbsp;
<span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">foreach</span><span style="color:#006600; font-weight:bold;">&#40;</span>ARGV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>line<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#9966CC; font-weight:bold;">next</span> <span style="color:#9966CC; font-weight:bold;">if</span> line.<span style="color:#9900CC;">strip</span> == <span style="color:#996600;">&quot;&quot;</span>
  cmd =  <span style="color:#996600;">&quot;mv <span style="color:#000099;">\&quot;</span>#{line.strip}<span style="color:#000099;">\&quot;</span> <span style="color:#000099;">\&quot;</span>#{destination}<span style="color:#000099;">\&quot;</span>&quot;</span>
  <span style="color:#008000; font-style:italic;">#puts cmd</span>
  <span style="color:#996600;">`#{cmd}`</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Bonus: In the process searching for this, I ran into the <a href="http://rubyquiz.com/quiz136.html">ID3 Tags RubyQuiz</a>.</p>
<p>One of the nicest benefits of being a software engineer is I avoid doing boring manual tasks on my computer. Writing a script is more fun, and faster. I&#8217;ve got many scripts to automate file manipulation, online banking, and more. What bit of your automation scripts do you think is the most helpful?</p>
]]></content:encoded>
			<wfw:commentRss>http://jawspeak.com/2009/09/05/ruby-script-to-organize-mp3s-based-on-id3-genre-tag/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Merging pdf&#8217;s on Mac OS X from a non-duplex scanner</title>
		<link>http://jawspeak.com/2009/08/05/merging-pdfs-on-mac-os-x-from-a-non-duplex-scanner/</link>
		<comments>http://jawspeak.com/2009/08/05/merging-pdfs-on-mac-os-x-from-a-non-duplex-scanner/#comments</comments>
		<pubDate>Wed, 05 Aug 2009 13:41:57 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[automation]]></category>

		<guid isPermaLink="false">http://jawspeak.com/?p=107</guid>
		<description><![CDATA[Reading time: 2 &#8211; 3 minutes

			
				
			
		
Goal: scan in hundreds of duplex documents in a non-duplex scanner and combine into 1 pdf in automated way. Status: it was harder than it should have been, and not that automated, but this works.
Scan in the papers as pdf&#8217;s from your paper-feed equipped scanner. Scan them right side up, [...]]]></description>
			<content:encoded><![CDATA[<p>Reading time: 2 &#8211; 3 minutes</p>
<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fjawspeak.com%2F2009%2F08%2F05%2Fmerging-pdfs-on-mac-os-x-from-a-non-duplex-scanner%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=?url=http%3A%2F%2Fjawspeak.com%2F2009%2F08%2F05%2Fmerging-pdfs-on-mac-os-x-from-a-non-duplex-scanner%2F&amp;style=normal&amp;service=bit.ly" height="61" width="51" /><br />
			</a>
		</div>
<p>Goal: scan in hundreds of duplex documents in a non-duplex scanner and combine into 1 pdf in automated way. Status: it was harder than it should have been, and not that automated, but this works.</p>
<p>Scan in the papers as pdf&#8217;s from your paper-feed equipped scanner. Scan them right side up, then flip over and scan the other sides. The two pdf&#8217;s will contain pages: 1, 3, 5&#8230; and 2, 4, 6&#8230;</p>
<p>Reverse the even pages.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;">#!/usr/bin/ruby</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0000FF; font-weight:bold;">__FILE__</span> == $<span style="color:#006666;">0</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;Run this on ubuntu or somewhere that pdftk is easy to be had. (which isn't os x)&quot;</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">if</span> ARGV.<span style="color:#9900CC;">length</span> != <span style="color:#006666;">1</span>
    <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;Syntax: #{__FILE__} pdf_to_reverse.pdf&quot;</span>
    <span style="color:#CC0066; font-weight:bold;">exit</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  pdf = ARGV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  reversed_pdf = pdf.<span style="color:#CC0066; font-weight:bold;">gsub</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>\.<span style="color:#9900CC;">pdf</span><span style="color:#006600; font-weight:bold;">/</span>i, <span style="color:#996600;">&quot;_reversed.pdf&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  page_count = <span style="color:#996600;">`pdfinfo #{pdf} | grep Pages`</span>.<span style="color:#9900CC;">scan</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>\d<span style="color:#006600; font-weight:bold;">+/</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  <span style="color:#996600;">`pdftk #{pdf} cat #{page_count}-#{1} output #{reversed_pdf}`</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Lastly, combine the two pdf&#8217;s, shuffling every other page, starting with the odds. Note it has some dependencies on pdftk and pdfinfo for the reversing (which are excruciatingly difficult to install on os x), and os x (for the merging).</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;">#!/usr/bin/ruby</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0000FF; font-weight:bold;">__FILE__</span> == $<span style="color:#006666;">0</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;Run this on os x to shuffle two pdf's, where the
        even pages are already reversed (reverse them with other script)&quot;</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">if</span> ARGV.<span style="color:#9900CC;">length</span> != <span style="color:#006666;">3</span>
    <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;Syntax: #{__FILE__} odds.pdf reversed_evens.pdf output.pdf&quot;</span>
    <span style="color:#CC0066; font-weight:bold;">exit</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  odds_pdf = ARGV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  reversed_evens_pdf = ARGV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  output_pdf = ARGV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#93;</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># obviously, only works on os x.  I didn't see an easy way to combine pdf's</span>
  <span style="color:#008000; font-style:italic;"># in pdftk or other tools I searched for</span>
  <span style="color:#996600;">`python '/System/Library/Automator/Combine PDF Pages.action/Contents/Resources/join.py' --output '#{output_pdf}' --shuffle '#{odds_pdf}' '#{reversed_evens_pdf}'`</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>References:</p>
<ul>
<li> <a href="http://www.accesspdf.com/pdftk/">pdftk</a> &#8211; pdf toolkit, I could have installed with ports install pdftk, but that has a <a href="http://www.oreillynet.com/onlamp/blog/2004/08/my_adventure_with_pdftk.html">very long</a> build dependency on gcj.</li>
</ul>
<ul>
<li><a href="http://www.ourada.org/blog/archives/15"> Reversing pages with pdftk</a></li>
</ul>
<ul>
<li> Another technique which would work if you didn&#8217;t need to reverse pages, using <a href="http://forums.macosxhints.com/archive/index.php/t-95412.html">automator</a>. And <a href="http://www.macosxhints.com/article.php?story=20060327192826493">without</a> automator (like I do with a script directly).</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://jawspeak.com/2009/08/05/merging-pdfs-on-mac-os-x-from-a-non-duplex-scanner/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

