Changing the shebang of ruby files best way?

I’ve a lot of ruby files (grabed from net) having a wrong shebang for my
setup.

actual shebang is :
#!/usr/bin/ruby -w

and i need to change it to :
#! /usr/bin/env ruby -w

that way i’ll get the ruby in my PATH and not a fixed ruby.

what i plan to do :

detect if the shebang isn’t correct and if true :
move the file to a temp directory
create a new with “good” shebang having path/name of the previous

remove the tmp dir

but i wonder, because i know i have to change the first line only, if i
could change the uncorrect file “in place” even if my shebang line is
longer (4 chars) than the preceeding one ???

On Fri, Jun 27, 2008 at 3:22 PM, Une Bévue
[email protected] wrote:

I’ve a lot of ruby files (grabed from net) having a wrong shebang for my
setup.

actual shebang is :
#!/usr/bin/ruby -w

and i need to change it to :
#! /usr/bin/env ruby -w

for file in *.rb; do
cp $file $file.tmp
sed -e “s/#!/usr/bin/ruby\ -w$/#!/usr/bin/env\ ruby\ -w/g”
$file.tmp >$file
rm $file.tmp
done

Greg D. [email protected] wrote:

for file in *.rb; do
cp $file $file.tmp
sed -e “s/#!/usr/bin/ruby\ -w$/#!/usr/bin/env\ ruby\ -w/g”
$file.tmp >$file
rm $file.tmp
done

fine, thanks, i’ll switch from ruby to zsh :wink:

Greg D. wrote:

for file in *.rb; do
cp $file $file.tmp
sed -e “s/#!/usr/bin/ruby\ -w$/#!/usr/bin/env\ ruby\ -w/g”
$file.tmp >$file
rm $file.tmp
done

Or as sh and Ruby:

for file in *.rb; do
ruby -p -i.bak -e ‘$_.sub!(%r{(#!)(/usr/bin/ruby)( -w)?},
“\1/usr/bin/env ruby -w”)’ “$file”
done

Or using find and Ruby to recurse the entire tree:

find . -type f -name ‘*.rb’ -exec ruby -p -i.bak -e
‘$_.sub!(%r{(#!)(/usr/bin/ruby)( -w)?}, “\1/usr/bin/env ruby -w”)’ {}
;

The “-i.bak” tells Ruby to do in-place replacements and backup originals
to that file extension.

-igal

On Jun 27, 2008, at 13:22 , Une Bévue wrote:

I’ve a lot of ruby files (grabed from net) having a wrong shebang
for my
setup.

actual shebang is :
#!/usr/bin/ruby -w

and i need to change it to :
#! /usr/bin/env ruby -w

the problem is that /usr/bin/env absolutely sucks on linux. -w is not
only NOT passed as an argument to “ruby”, it is considered part of
ruby (eg “ruby -w”) and horks the exec.

If you’re tweaking shebang lines JUST FOR YOU, this is fine… but I
get a bunch of tickets filed against my software that it doesn’t work
for them (mitigated by installing via rubygems). I try to tell them to
file a bug against their linux distro, but they don’t seem to agree
with me most of the time. :slight_smile:

On Sat, Jun 28, 2008 at 2:41 PM, Ryan D. [email protected]
wrote:

the problem is that /usr/bin/env absolutely sucks on linux. -w is not only
NOT passed as an argument to “ruby”, it is considered part of ruby (eg “ruby
-w”) and horks the exec.

You can set $VERBOSE, $-w, or $-v to true to get the same effect as ruby
-w.

On Sat, Jun 28, 2008 at 3:41 PM, Ryan D. [email protected]
wrote:

the problem is that /usr/bin/env absolutely sucks on linux. -w is not only
NOT passed as an argument to “ruby”, it is considered part of ruby (eg “ruby
-w”) and horks the exec.

FWIW, the problem here is not ‘env’, it’s the way that ‘#!’ lines are
parsed. The ‘env’ will do the correct thing if it is given separate
parameters, but the kernel-level exec processor does not parse out all
the
individual fields in a ‘#!’-line. It parses “the executable” and
“everything else”, and then passes “everything else” as a single
parameter
to “the executable”. And at this point, it would be much too
incompatible a
change to have the exec processor parse it in any other way. There’s
even
some logic to the way that parsing is done, although I don’t remember it
at
the moment.

The ‘env’ command in FreeBSD provides a way around this, by adding some
more
options to ‘env’ so it can parse out the individual options, but I don’t
know if any other OS’s will notice that and pick up the options. (note:
I’m the guy who added those options to ‘env’ in FreeBSD…)

e [email protected] wrote:

Just create a symbolic link to /usr/bin and leave the shebang

there is another ruby there…
the default ruby (Apple installed) is under /usr, the used ruby is under
/opt, i’m using the latest…

On Jun 29, 2008, at 10:09 , Greg D. wrote:

On Sat, Jun 28, 2008 at 2:41 PM, Ryan D. <ryand-
[email protected]> wrote:

the problem is that /usr/bin/env absolutely sucks on linux. -w is
not only
NOT passed as an argument to “ruby”, it is considered part of ruby
(eg “ruby
-w”) and horks the exec.

You can set $VERBOSE, $-w, or $-v to true to get the same effect as
ruby -w.

what about -s? or a myriad of other options…

Actually relying on env in itself as absolute path is pretty weird.
After all, env is supposed to do away with the problems imposed by the
FHS.

I wonder whether the first shebang line could not just simply be “env”
instead (or the binary in question, without absolute path) and then
there would be a simple file where one could tell env which path should
be used.

On Jun 29, 2008, at 20:59 , Garance A Drosehn wrote:

The ‘env’ command in FreeBSD provides a way around this, by adding
some more
options to ‘env’ so it can parse out the individual options, but I
don’t
know if any other OS’s will notice that and pick up the options.
(note:
I’m the guy who added those options to ‘env’ in FreeBSD…)

I’ve been told that FreeBSD is going to start acting like linux in
this regard… is that true?

(apologies if my previous message to this thread
is wrapped very weirdly…)

On Mon, Jun 30, 2008 at 4:31 PM, Marc H. [email protected]
wrote:

Actually relying on env in itself as absolute path is pretty weird.
After all, env is supposed to do away with the problems imposed
by the FHS.

It is a little weird, but I think it’s the best tactic we’ve got for
now.

I wonder whether the first shebang line could not just simply be “env”
instead (or the binary in question, without absolute path) and then
there would be a simple file where one could tell env which path
should be used.

The problem is getting this new idea implemented on a large
number of platforms. If you are writing scripts for a single
platform (say, “redhat linux”), then there is no problem using
‘/bin/env’ or ‘/usr/bin/env’ (both of which exist on the linux
machine I’m looking at).

If you’re going to run your scripts on many platforms, and if
you do not like the hard-coded path to ‘env’, then you need to
come up with some new solution. The problem is that you then
have to get that solution implemented on every platform that
you care about. Until you do get it available everywhere,
then you’re going to have to fall back to some other solution
for some of the platforms.

On Mon, Jun 30, 2008 at 3:14 PM, Ryan D. [email protected]
wrote:

On Jun 29, 2008, at 20:59 , Garance A Drosehn wrote:

The ‘env’ command in FreeBSD provides a way around this, by adding some more
options to ‘env’ so it can parse out the individual options, but I don’t
know if any other OS’s will notice that and pick up the options. (note:
I’m the guy who added those options to ‘env’ in FreeBSD…)

I’ve been told that FreeBSD is going to start acting like linux in this regard… is that true?

I’m not sure what you mean. The last I checked, freebsd parses the
‘#!’ line in the0
same way that Linux, Solaris, and a few other unixes did. FreeBSD
used to have
a different way for parsing that line, but a few years ago I fixed it
to parse the line
the same way every other unix parses it.

As for the ‘env’ command, the version on FreeBSD is pretty much the
same as `env’
on other unixes, except that I added a few new options which can be very
useful
when using ‘env’ on a ‘#!’ line. Admittedly I have not checked the
latest versions of
linux though, so maybe they added some other options to ‘env’.

So I don’t know what you are referring to when you ask if it is going
to start acting
like linux…

On Sunday 20 July 2008 15:32:55 Garance A Drosehn wrote:

The problem is getting this new idea implemented on a large
number of platforms.

How about via RubyGems? (Assume we can use more complex workarounds to
get
RubyGems installed…)

Just have RubyGems detect the platform, and, when it installs a script
for a
particular Gem, have it add the appropriate shebang.

On Jul 20, 2008, at 13:10 , Garance A Drosehn wrote:

(note:
I’m the guy who added those options to ‘env’ in FreeBSD…)

I’ve been told that FreeBSD is going to start acting like linux in
this regard… is that true?

I’m not sure what you mean. The last I checked, freebsd parses the
‘#!’ line in the0 same way that Linux, Solaris, and a few other
unixes did. FreeBSD used to have a different way for parsing that
line, but a few years ago I fixed it to parse the line the same way
every other unix parses it.

What I meant was, currently all the versions of freebsd that I use as
well as OSX do a good job of parsing the shebang line so that options
and/or trailing arguments are not considered part of the executable
name. That is decidedly NOT the case on linux and a constant PITA as
far as I’m concerned.

not all ruby command line options have any other equivalent way of
activating their functionality. For example, while -I has $:/
$LOAD_PATH, -s has no analogous enabler. This means either I can’t use
the functionality or I can’t use /usr/bin/env because it’ll break on
linux. :confused:

On Mon, Jul 21, 2008, Ryan D. [email protected] wrote:

can’t use the functionality or I can’t use /usr/bin/env because
it’ll break on linux. :confused:

For what it’s worth, this is what I do for a safe cross-platform way
to avoid the problem. You could obviously skip the section on setting
a new value for PATH, but my environment is such that ruby believes
some directories in my PATH are world-writeable, when in fact they
are not.

#!/bin/sh

-------±--------±--------±------- +

--------±--------±--------±--------+

/ This section is a safe way to find the interpretter for ruby,

\

| without caring about the user’s setting of PATH. This reduces

|

| the problems from ruby being installed in different places on

|

| various operating systems. A much better solution would be to

|

| use /usr/bin/env -S-P' , but right now -S-P’ is available

|

\ only on FreeBSD 5, 6 & 7. Garance/2005

/
OSRUBYBIN=
for fname in /usr/local/bin /opt/csw/bin /opt/local/bin /usr/bin ; do
if [ -x “$fname/ruby” ] ; then OSRUBYBIN=“$fname/ruby” ; break; fi
done
if [ -z “$OSRUBYBIN” ] ; then
echo “Unable to find a ‘ruby’ interpretter!” >&2
exit 1
fi
export OSRUBYBIN

Set a safe value for PATH here, as the cheapest way to avoid the

annoying ruby message: “warning: Insecure world writable dir …”

Make a copy of the user’s original PATH, in case the script needs

it.
PATH_PRERUBY=“$PATH”
export PATH_PRERUBY
PATH=“/bin:/sbin:/usr/local/bin:/usr/bin:/usr/sbin”
export PATH

eval ‘exec “$OSRUBYBIN” -x -S $0 ${1+“$@”}’
echo “The ‘exec "$OSRUBYBIN" -x -S …’ failed!” >&2
exit 1
#! This #!-line starts the real script, due to the marker: ruby

-------±--------±--------±------- +

--------±--------±--------±--------+
p “Hello World”
exit 0