The *nix Rube Goldberg Machine – .bat;.cmd done better

Learn your shell!

My primary work machine is Ubuntu *happy face* but my day to day work is in a windows VM *sad face*

Our project uses a lot of nugets packages and some of those nugets bring in command line tools that we use while developing our project. For example we use a tool called bottles that can package our application up into “deployable zipfiles”.

Anyways that tools comes into our project via nuget, but I have to call that tool from the command line all the time. So my coworkers made a batch file that will find the exe in the nuget packages folder and delegate all the command line argument to it so we can all bottles from the root of our project like this

~/lecode/leproject>bottles create-all

Here’s the source code for that cmd file.

REM Find BottleRunner in one of the installed Bottles nuget packages
FOR /R %~dp0\source\packages %%G IN (BottleRunner.exe) DO (
      SET RUNNER=%%G


ECHO BottleRunner.exe not found.

Pretty simple, it runs a for loop looking for any files named BottleRunner.exe and sets a variable. Then it checks if that variable was found and does a GOTO *gasp* delegating arguments to the exe.

That’s all well and good but I want to run bottles from bash, cause I’m in bash way more that cmd and lets face it I hate cmd.exe and don’t want to use it.

So I came up with this piece of awesome.

for exe in `find source/packages -type d | sort -r | grep "Bottles\.Tools" | sed -n 1p | xargs grep -rl "BottleRunner\.exe" | sed -n 1p`; 
    $exe $@; 

find source/packages -type d | sort -r | grep "Bottles\.Tools" | sed -n 1p | xargs grep -rl "BottleRunner\.exe" | sed -n 1p

Holy crap! that’s a nasty one, what does it do?

find source/packages -type d
Find all directories (-type d) in the source/packages folder

find source/packages -type d | sort -r
Pipe that into sort in order to sort it descending (-r)

find source/packages -type d | sort -r | grep "Bottles\.Tools"
grep for folders that contain Bottles.Tools

find source/packages -type d | sort -r | grep "Bottles\.Tools" | sed -n 1p
Only print the first line (-n 1p) so that the highest version number gets printed

find source/packages -type d | sort -r | grep "Bottles\.Tools" | sed -n 1p | xargs grep -rl "BottleRunner\.exe"
Recursively search that directory (-r) for for files named BottleRunner.exe and print out the file path (-l)

find source/packages -type d | sort -r | grep "Bottles\.Tools" | sed -n 1p | xargs grep -rl "BottleRunner\.exe" | sed -n 1p
Print the top line in case there is a config file BottleRunner.exe.config

for exe in `find source/packages -type d | sort -r | grep "Bottles\.Tools" | sed -n 1p | xargs grep -rl "BottleRunner\.exe" | sed -n 1p`; do $exe $@; done
Throw that into a for loop so that I can delegate all of the arguments ($@) to the latest bottlerunner.exe

You can use that to delegate to other tools as well just change “Bottles.Tools” with the name of you nuget and BottleRunner.exe to the name of the exe you want.

Now I can safely run bottles from bash

bottles create-all

So much WIN!

Don’t herp derp it, use my sweet script and avoid cmd.exe


About Ryan Rauh

My name is Ryan Rauh and I like shiny things. If I've seen it on twitter more the twice most likely I've looked at it or tried it. I really like memes and other silly and seemingly useless things out on the internet. I blog about things *I* think are cool and interesting, I hope you will find them cool and interesting too.
This entry was posted in Shell and tagged . Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Matt

    Which bash environment are you using on Windows? Cygwin? Msys? Something else?

    • Anonymous

      I use msys, specifically the default install that you get when you install msysgit. 

  • Boy, you could use couple of hours learning powershell.

  • Seth Stone

    Would you be able to just do this?:

      echo $(find . -name ‘BottleRunner.exe’ | sort -r | head -1) $

    (comment field wouldn’t let me put an at sign)

    • Seth Stone

      Sorry… w/o the word echo

    • Anonymous

      Sweet, yeah that works much better! BTW I didn’t know you could use the $() syntax like that. 

      That’s why I was using the for loop so that I could pass along the arguments.

      This is way mo ‘betta