Noel Rappin Writes Here

Automator + Bash = Yay

Posted on June 6, 2012

At it’s best, working in Mac OS X combines the power of the Unix shell with the convenience of an actual interface.

Here’s a best case scenario:

As I may have mentioned here a few times, I’m writing a book. As part of my current workflow, I need to convert my text from it’s old format to my new format, which is Markdown. The old format is a custom XML-based language the details of which don’t matter beyond the fact that it’s XML-based.

Moving the text over has two issues:

  • The obvious one is that there are XML tags in the body of the text for things like code literals and text italics that I want to replace with either the Markdown backtick or the Markdown underscore.
  • The less obvious one is that when writing XML text, I treat it like code, meaning I’m ridiculously insane about text layout. In my XML source, I really do still insist on an 80-character line, with hard returns and indentation. I’ve decided that I don’t need to do this when I write in Markdown, so when I move the text over, I need to get rid of all the hard returns and spacing.

What I’d like is a workflow where I can copy a paragraph of text to the clipboard, do magic, and then paste cleaned-up text in the new book file. Going a paragraph at a time is not a problem — it’s actually preferable, since I’m editing as I go, so moving a whole file at a time is not really what I want.

I toyed with the idea of doing this in Ruby, but that seemed like a pain, so I wrote a short shell script.

Understand: I never do this, and I pretty much know beans about the shell programs involved. But by googling things like “shell remove newlines” and with some helpful man pages, I cobbled together the following, with details of the XML fuzzed a bit.

    pbpaste | tr -d '\n' | tr -s ' ' |
    sed -E 's/<\/*(literal|lit)>/\`/g' |
    sed -E 's/<\/*(italic|bold)>/\*/g' | pbcopy

All of you who actually know shell scripting are invited to have a hearty laugh. While you are off chuckling, I’ll explain what this line noise does…

  • pbpaste takes the text from the clipboard, which is piped to…
  • tr -d '\n', which removes all the newlines, and pipes to…
  • tr -s ' ', which removes duplicate spaces, and pipes to…
  • sed -E 's/<\/*(literal|lit)>/\/g’`, which takes all the XML tags for things that I want replaced with Markdown literal syntax and puts in a back tick, then pipes to…
  • sed -E 's/<\/*(italic|bold)>/\*/g', takes the XML tags I want to replace with Markdown emphasis syntax, then pipes to…
  • pbcopy, which copies the final text back into the clipboard

Works great. A bit of a mouthful to type, if I can mix metaphors. (The actual one is even more complicated, because I strip out some XML entities as well). It’s a bit much to type at the terminal in my workflow. Creating an alias is a possibility, but still, requires a terminal.

There’s another option in Mac OS X, though: Automator.

You may not have played with Automator, because you do not fully appreciate Automator. Automator is an OS X application that lets you chain together predefined actions (very similar to the actions exposed via apple script), using a GUI interface, and save the result as an application or an OS X service, among other options.

This isn’t an Automator tutorial, because what I want to do here is really simple. One of the available actions in Automator is “Run Shell Script”.


I created a new Automator document as a Service, added the Run Shell Script action to it, pasted my big shell script into the body of the action. The action doesn’t need input. Even better, I can have it work not on the clipboard, but on the selected text in the open application, which saves me a step in my workflow. The shell script is already putting the output on the clipboard, so I don’t need to deal with that in automator either.

Okay, big deal, it runs a shell script. But, since I’ve saved it as a service, I can assign a global key command to it. In the System Preferences for Keyboard, my new service is somewhere in the Keyboard Shortcuts tab (under services). From there, I can assign a keyboard shortcut, which is available in any application that exposes itself to services, which is many applications.

Now I just select a paragraph of old text in my text editor, hit my new key combination, and I can paste the cleaned up text in my new editor window. A little Unix, a little Mac, and a lot of time saved.


comments powered by Disqus

Copyright 2024 Noel Rappin

All opinions and thoughts expressed or shared in this article or post are my own and are independent of and should not be attributed to my current employer, Chime Financial, Inc., or its subsidiaries.