#! /usr/bin/env ruby require 'rbconfig' require 'tempfile' require 'fileutils' require 'rubygems' gem 'main', '2.8.2' require 'main' Main { name "shebangify" description " shebangify is a script that adds the correct shebang line according to the ruby version running the script. for instance, if you had ruby 1.8.7 installed as ruby187 and ruby 1.8.6 installed as ruby186 you could do ruby187 foo.rb bar.rb to have foo.rb and bar.rb adjusted such that the shebang line would be #! /full/path/to/ruby187 or ruby186 foobar.rb to have foobar.rb have it's shebang line adjusted to #! /full/path/to/ruby186 run simply as 'shebangify' the script is going to adjust to the first ruby in your path which would normally be the latest one. shebangify accepts one, or more, filenames on the command-line. if command-line of '-' to indicate reading a list of files to shebangify on STDIN " option("ruby"){ description "path to ruby to use in shebang line" cast{|path| File.expand_path path} attr } argument("paths"){ description "one or more paths to shebangify, '-' reads paths from stdin" arity -1 attr } def run each_path{|path| shebangify?(path){ puts path }} end def each_path &b stdin = paths.delete('-') paths.push(*STDIN.readlines) if stdin paths.each do |path| next if path.strip.empty? b.call File.expand_path(path) end end def shebangify? path, &b re = %r/^\s*#\s*!/o pid = Process.pid basename = File.basename path fullpath = File.expand_path( ruby || which_ruby ) shebang = "#! #{ fullpath }" fu = FileUtils lines = IO.readlines(path) matched = false while(( line = lines.first )) match = re.match line blank = line.strip.empty? if match or blank matched = true if match lines.shift else break end end if matched bak = "#{ path }.bak" fu.cp path, bak open(path, 'w'){|fd| fd.puts shebang, "\n", lines} fu.rm_f bak b ? b.call(path) : path else false end end def which_ruby c = Config::CONFIG bindir = c["bindir"] || c['BINDIR'] ruby_install_name = c['ruby_install_name'] || c['RUBY_INSTALL_NAME'] || 'ruby' ruby_ext = c['EXEEXT'] || '' ruby = File.join(bindir, (ruby_install_name + ruby_ext)) end }