The Beauty of &&

I’m a big fan of bash. The first thing I do on any windows computer is install another browser, and the second thing I do is install cygwin. Cygwin gives me bash on windows, and fortunately on macs, OS X is based on unix, so bash is already there.

Don’t get me wrong, I’m not a true unix-head by any means. I don’t live on the command line, I just know how to get things done with it. I don’t prefer emacs or vi over a gui editor, and I couldn’t tell you the history of bash, or whether bash is better than another shell option (aside from DOS, as any shell is better than that). And, honestly, there are quite a few linux commands that I’m not sure whether they’re bash built-in commands or separate programs entirely. And the great part is, none of that matters, bash is easy enough for an impatient guy such as myself to use and get things done. That’s the bit I like about it.

Bash is not without flaws. I will never like the syntax for some of bash’s internal string operations, they look too perl (write only) to me. Other bits, like “do” and “done” delimiters instead of curly braces remind me enough of DOS batch to make me cringe every time I type them. And those are just the superficial easy-to-deal with problems that I can recall because I haven’t automatically filed them in the “too painful to think about” defense mechanism locked-off zone in my head.

Here’s the thing. Bash is easy to understand, easy to use, well documented, and portable. Like Java for heavier programmatic lifting, I can pretty much “write once, run anywhere” with bash scripts. That portability alone is enough for me to put up with bashisms that inspire rage.

Further, there’s typically more than one way to solve a problem. When regex madness with sed is causing screaming fits, often a simple trick with awk can greatly simplify things for you. Or perhaps you should flip the whole problem on its head and throw a few extra grep commands earlier in the command pipeline to make your life easier later down the chain. The exec syntax for find inspires madness, and yet xargs can set you free. There are a thousand little examples where these common unix tools are like differing swiss army knife models. Usually one of them does a thing or two well, and at least half-asses a few more things too, but chances are when you hit some pain, another tool does that bit easier and more sanely.

Contrast this all with batch scripts and go-tos and syntax from hell that just feels wrong to write. Comment out a line with “REM”, seriously?

Anyway, I digress..

The whole point of this is to say that && is awesome. I’ve been using bash for years, and have known about using && on the command line in theory for a while. The theory goes you can do something like this:

  1.  cmd1 && cmd2

When you do that, if cmd1 executes without returning an error code, cmd2 will run as well. Great, kinda, until you put 2 and 2 together and realize that you can basically chain commands with && forever.

An example, I had to run these commands recently over and over:

  1.  mkdir tmp
  2.  hadoop dfs -copyToLocal /some/dir tmp
  3.  cd tmp
  4.  cp -R * ../SomeFolder
  5.  cd ..
  6.  rm -Rf tmp

Don’t worry for what’s really going on or if I could have done something with less commands, the point was I had to use several commands, and it was a pain in the ass to hit the up key on my keyboard to execute them in sequence every 5 minutes to get some real work done. After doing that a couple of times, I initially resolved to write a one-time script with a 1 hour lifespan of utility to me, then delete it. I almost cracked my editor open when it occurred to me that I could just do this instead, on the command line:

  1.  mkdir tmp && hadoop dfs -copyToLocal /some/dir tmp && cd tmp && cp -R * ../SomeFolder && cd .. && rm -Rf tmp

This made it simple for me to get work done, quickly. I’d simply test something, return to my terminal window, hit the up key once, and hit enter. THAT is the beauty of bash, and by extension: &&.

Alternatively, you can separate commands with a semicolon and have the entire chain execute no matter if any of the commands result in error:

  1. mkdir tmp; hadoop dfs -copyToLocal /some/dir tmp; cd tmp; cp -R * ../SomeFolder; cd ..; rm -Rf tmp

If you’re into bash, or looking to learn about it, here’s the short list of resources to get you going.

  • Advanced Bash Scripting Guide – don’t let the “Advanced” part scare you, this is *the* resource for learning bash from zero to zen master. Every little bit of bash scripting is explained with hundreds of real-life examples sprinkled throughout the text.
  • Bash Cures Cancer – the most amazingly named blog on the intrenet, ever. and it’s all true too. loads of great little tips and tricks here.
  • Bash on Wikipedia
  • bash.org – not about bash the shell/programming language at all, but amazing and just as essential.
  • cygwin – a free set of programs that’s basically a little unix on top of windows. bash comes as part of the base installation, but also check out optional install stuff like ‘openssh’, ‘apache’, ‘wget’, and others.
  • homebrew – a great os x package manager, like cygwin on windows, this guy provides the unix tools you’re familiar with that don’t come in the stock OS X install, such as md5sum, or watch, etc.