Last Updated: February 25, 2016
· nat-n

Execute a rakefile as a bash script

This may be crazy, but it turns out you can execute a file as a bash script which then executes itself as a rakefile (or a regular ruby script in principle) like so.

#!/usr/bin/env bash
sleep 0 \
=begin 2> /dev/null
exec rake -f $0 $@

desc 'The tasks at hand'

task :hello do
  puts "hello to you too!"

What's happening here is that when the script is executed by bash, it executes lines 2 and 3 as a single line which invokes the sleep command like sleep 0 =begin and pipes the resulting error to /dev/null as if nothing ever happened. It then invokes exec to replace the current process with rake executing the same file with the same arguments.

When rake/ruby reads the file it ignores the shebang on line one, sees sleep 0 which is valid and does essentially nothing on line 2, then sees a block quote which it ignores on lines 3-5 before moving on to the ruby code.

Yes it's less efficient, but the difference is non-significant compared to the time taken for rake to be invoked (>100ms).

In most cases it's probably better to write a regular rakefile and create an alias like alias foo='rake -f ~/bin/foo' or whatever, but in case that doesn't work for you this hack might just help.