Bash Hackery

This morning I found myself playing with bash commands trying to move a bunch of dirtied files to a Subversion change list. Most people find themselves after searching for years in college, others find themselves after volunteering for a mission or going on a trip to another country. Not me, I find myself in the middle of an iTerm session trying to make sense of a bunch of text files that have been dirtied (modified) by an improperly factored project structure after running a build which doesn’t restrict its output to one path. Hi, I’m Cliff. You’re here because you’d like to make sense of a bunch of files on your hard drive. Maybe you’re in a situation similar to mine. Maybe you just like hacking with shell commands, piping the output of one command into the input of another. I’m here to explain what I learned this morning.

I was frustrated because “svn st” kept spewing out a bunch of modified files for my project and I hadn’t made source changes. I modified some setting in Eclipse to get things to compile but that was the extent. I use change lists in IntelliJ all the time and I know you can do the equivalent from the command line using Subversion. So I get to hacking with awk and grep and paste to try and make sense of “svn st” output. Here’s what I came up with.

svn st
(Lists all modified files, but you probably already knew that.)
? .idea/scopes
? .idea/workspace.xml
? atlassian-ide-plugin.xml
? out
? awesome-android-ad-api/bin
M awesome-android-app/.classpath
? awesome-android-app/build/retrieve-ivy.xml
? awesome-android-app/libs/awesome-android-ad-api.jar
? awesome-android-app/libs/awesome-android-ad-impl.jar
? awesome-android-app/lint-report-formatted.xml
? awesome-android-app/lint-report.html
? awesome-android-app/lint-report.xml
M awesome-android-app/.classpath
M thirdparty/XPartyManagedView/lib/.classpath
M thirdparty/HockeySDK-Android/.classpath

svn st | grep -e ‘.classpath’
(list only ‘.classpath’ project files modified, this filters my output for the changes I made in my Eclipse settings.)
M awesome-android-app/.classpath
M thirdparty/XPartyManagedView/lib/.classpath
M thirdparty/HockeySDK-Android/.classpath

svn st | grep -e ‘.classpath’ | awk ‘{print($2);}’
(Print only the 2nd column from the earlier svn output which we filtered with grep. It’s pretty cool because now we’re getting to the actual files we want to operate on.)

paste -d ‘ ‘ -s <(svn st | grep -e '.classpath' | awk '{print($2);}')
(Flatten the one column output above listing only the file names into a single line delimited with a single space ‘ ‘ character. This is even better because now all of the files can be passed as a parameter to a shell command but how do we do that?)
awesome-android-app/.classpath thirdparty/XPartyManagedView/lib/.classpath thirdparty/HockeySDK-Android/.classpath

svn changelist “‘Eclipse project modifications.'” `paste -d ‘ ‘ -s <(svn st | grep -e '.classpath' | awk '{print($2);}')`
(We use back ticks “`” to return the value of our piped command chain as a parameter to the svn change list command and viola!)
A ['Eclipse project modifications.'] awesome-android-app/.classpath
A ['Eclipse project modifications.'] thirdparty/XPartyManagedView/lib/.classpath
A ['Eclipse project modifications.'] thirdparty/HockeySDK-Android/.classpath

All thanks to the magic of grep and awk. You can do all kinds of magic by chaining awk to grep to see and piping into past or whatever combination your mind can imagine. It just takes a little patience to familiarize with the command line flags and things like regex. Once you get the hang of it you’ll be flying…

Mac Automator tip of the day

So I was looking in TextMate for one of my most favorite tools from IntelliJ. It’s the “Compare with clipboard” action that takes whatever you have selected and runs a side-by-side diff with whatever is on your clipboard. I thought for sure it would exist in TextMate but I was disappointed so I built my own using Automator. See the pic below for the entire source. (There’s gotta be a better way to share Automator source but I’m in a hurry and lazy so there ya’ go.) This workflow depends on Xcode’s FileMerge but you can substitute whatever diff tool you’re comfortable with. To create it, start Automator and select System service from the “New…” action then copy in the actions from the image. Name it “Compare selection with clipboard” and then where ever you are in your Mac you will have access to the tool from the context menu (right clicking) of any selection.

Automator workflow
Compare selection with clipboard

When I first posted this there was a small bug. I changed the get clipboard step to an Applescript command “get the clipboard” since the built-in Automator task returns styled text instead of raw text.