Irb: a great tool in it's own right

irb (and a little Ruby knowledge) is great for system tasks, especially on
Windows where the command-line tools are generally lacking.

For example:
We're migrating from VC++ 6.0 to VC++ 7.0 (Visual Studio .NET, or whatever
the heck they call it now) so we had to migrate a bunch of projects to to
the new project format. Now instead of .dsw and .dsp files they use
..vcproj and .sln files. These things are all over the directory tree so
chasing them all down and adding them to cvs is a bit of a pain (and there
are about 20 of them)... But it's no problem in irb:

projfiles = Dir["**/*.vcproj"]

  [ list of vcproj files ]

slnfiles = Dir["**/*.sln"]

  [ list of sln files ]

files = projfiles + slnfiles

  [ list of both ]

files.each {|f|
  `cvs add #{f}`
}

....done.

Phil

Yup -- it's like a shell with (*gasp*) intelligent handling of
intermediate results like lists of filenames. At times, I've even
defined a 'method_missing' in my irb toplevel which just calls 'system'
to invoke a command, rather than method, which makes irb even more
shell-like. Of course, you still have to pass arguments to those
commands as an array of strings, but I've found that %w{ ... } works
well.

rcoder@gmail.com wrote:

Yup -- it's like a shell with (*gasp*) intelligent handling of
intermediate results like lists of filenames. At times, I've even
defined a 'method_missing' in my irb toplevel which just calls 'system'
to invoke a command, rather than method, which makes irb even more
shell-like. Of course, you still have to pass arguments to those
commands as an array of strings, but I've found that %w{ ... } works
well.

Just in case anyone is really interested, the def is

~ def method_missing( method, *args )
~ system method.to_s + " " + args.join(' ')
~ end

and you could perhaps call

~ dir %w{ *.rb }

++ for the method missing comment !

- --
kaspar

semantics & semiotics
code manufacture

www.tua.ch/ruby

And

~ def method_missing( cmd, *args )
~ %x{#{cmd} #{args.join(' ')} }
~ end

might be considered more useful by some.

best regards,
kaspar

Or better:

  def method_missing(method, *args)
    system(method.to_s, *args)
  end

This work better when dealing with arguments which contain spaces (often a
bugbear of shell programming)

irb(main):004:0> touch "foo bar"
=> true
irb(main):005:0> ls "-l","foo bar"
-rw-r--r-- 1 brian brian 0 Oct 1 13:14 foo bar
=> true
irb(main):006:0> rm "foo bar"
=> true

Regards,

Brian.

···

On Fri, Oct 01, 2004 at 08:17:14PM +0900, Kaspar Schiess wrote:

Just in case anyone is really interested, the def is

~ def method_missing( method, *args )
~ system method.to_s + " " + args.join(' ')
~ end

Not to be a killjoy, but can't you just type:

  `ls foo bar`

Hmm.. actually you need a puts in front so

  def `(*args)
    puts super
  end

T.

···

On Friday 01 October 2004 07:17 am, Kaspar Schiess wrote:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

rcoder@gmail.com wrote:
> Yup -- it's like a shell with (*gasp*) intelligent handling of
> intermediate results like lists of filenames. At times, I've even
> defined a 'method_missing' in my irb toplevel which just calls 'system'
> to invoke a command, rather than method, which makes irb even more
> shell-like. Of course, you still have to pass arguments to those
> commands as an array of strings, but I've found that %w{ ... } works
> well.

Just in case anyone is really interested, the def is

~ def method_missing( method, *args )
~ system method.to_s + " " + args.join(' ')
~ end

... etc.

On the subject (if not the Subject:): Have anybody played with make it
possible to use Ruby for running sort-of shell scripts? Ie, including
pipes etc. As it is, there are some programs that call a lot of shell
commands that I write in sh instead of Ruby, and where I'd really like
to do them in Ruby.

The starting point I see for something like this would be to override
method_missing like above, but make it return an object where | is
overridden, and that have handling of shell return codes.

The challenges I see here is
- It's not possible to override the trueness/falseness of an object,
so we'd need to call a special method to find out if a command failed
or passed
- It is hard to implement -e (give an error if a complete shell line
fails - but not if we have an fail || true). Maybe trace_func could
be of help here, though.

Eivind.

···

On Fri, 1 Oct 2004 20:17:14 +0900, Kaspar Schiess <eule@space.ch> wrote:

Just in case anyone is really interested, the def is

~ def method_missing( method, *args )
~ system method.to_s + " " + args.join(' ')
~ end

and you could perhaps call

~ dir %w{ *.rb }

++ for the method missing comment !

Not necessary if you're running in irb, as it prints the expression return
value:

irb(main):004:0> `ls TODO`
=> "TODO\n"
irb(main):005:0>

But then you have more work when interpolating parameters:

  a = "foo bar"
  `touch "#{a}"`

(and that doesn't work for filenames which include double quotes)

Brian.

···

On Fri, Oct 01, 2004 at 10:09:44PM +0900, trans. (T. Onoma) wrote:

Not to be a killjoy, but can't you just type:

  `ls foo bar`

Hmm.. actually you need a puts in front so

  def `(*args)
    puts super
  end

"Eivind Eklund" <eeklund@gmail.com> schrieb im Newsbeitrag
news:dc9b20bb041001065332408f65@mail.gmail.com...

On the subject (if not the Subject:): Have anybody played with make it
possible to use Ruby for running sort-of shell scripts?

This topic arises from time to time. AFAIR there are IRB extensions that
make IRB shell-like.

Ie, including
pipes etc.

IO.popen() uses pipes internally. And I think there is also another
method.

As it is, there are some programs that call a lot of shell
commands that I write in sh instead of Ruby, and where I'd really like
to do them in Ruby.

Depending on what you do, you might notice that you don't need those shell
programs for the job. For example, "cat" is easily done with File.open()
{|io|...} and "rm" can be taken care of by File.delete().

The starting point I see for something like this would be to override
method_missing like above, but make it return an object where | is
overridden, and that have handling of shell return codes.

The challenges I see here is
- It's not possible to override the trueness/falseness of an object,
so we'd need to call a special method to find out if a command failed
or passed
- It is hard to implement -e (give an error if a complete shell line
fails - but not if we have an fail || true). Maybe trace_func could
be of help here, though.

I'm not sure whether I wanted Ruby scripts to look similar to shell
scripts or whether it's feasible to a degree that is satisfactory. I
wouldn't mind having a method pipe(*commands) in Kernel or IO that starts
all these commands in parallel and connects them via pipes. I imagine
usage like this:

IO.pipe( "ls -laf", "grep -v foo" ) do |io|
  # io like in IO#popen
  while ( line = io.gets )
    puts line
  end
end

Hm, this could even be an extension of IO#popen... Input of the IO
instance would then be connected to the output of the last command and
output would be connected to the input of the first command. That way one
could send data around through the pipe. Funny idea.

Kind regards

    robert

http://www.rubyist.net/~rubikitch/computer/irbsh/

-z

···

On Fri, 1 Oct 2004 22:53:07 +0900, Eivind Eklund <eeklund@gmail.com> wrote:

On Fri, 1 Oct 2004 20:17:14 +0900, Kaspar Schiess <eule@space.ch> wrote:
> Just in case anyone is really interested, the def is
>
> ~ def method_missing( method, *args )
> ~ system method.to_s + " " + args.join(' ')
> ~ end
>
> and you could perhaps call
>
> ~ dir %w{ *.rb }
>
> ++ for the method missing comment !

... etc.

On the subject (if not the Subject:): Have anybody played with make it
possible to use Ruby for running sort-of shell scripts? Ie, including
pipes etc. As it is, there are some programs that call a lot of shell
commands that I write in sh instead of Ruby, and where I'd really like
to do them in Ruby.

The starting point I see for something like this would be to override
method_missing like above, but make it return an object where | is
overridden, and that have handling of shell return codes.

The challenges I see here is
- It's not possible to override the trueness/falseness of an object,
so we'd need to call a special method to find out if a command failed
or passed
- It is hard to implement -e (give an error if a complete shell line
fails - but not if we have an fail || true). Maybe trace_func could
be of help here, though.

Eivind.

[snip]

On the subject (if not the Subject:): Have anybody played with make it
possible to use Ruby for running sort-of shell scripts? Ie, including
pipes etc. As it is, there are some programs that call a lot of shell
commands that I write in sh instead of Ruby, and where I'd really like
to do them in Ruby.

Not sure exactly what you're looking for, but perhaps you'd find the
Session library useful for driving external programs:

  http://raa.ruby-lang.org/project/session/

andrew

···

On Fri, 1 Oct 2004 22:53:07 +0900, Eivind Eklund <eeklund@gmail.com> wrote:

--
Andrew L. Johnson http://www.siaris.net/
      What have you done to the cat? It looks half-dead.
          -- Schroedinger's wife

"Eivind Eklund" <eeklund@gmail.com> schrieb im Newsbeitrag
news:dc9b20bb041001065332408f65@mail.gmail.com...

> On the subject (if not the Subject:): Have anybody played with make it
> possible to use Ruby for running sort-of shell scripts?

This topic arises from time to time. AFAIR there are IRB extensions that
make IRB shell-like.

I'm not thinking of IRB - I'm thinking of scripting specifically.

> Ie, including
> pipes etc.

IO.popen() uses pipes internally. And I think there is also another
method.

Yes, but these are highly clumsy when doing complex operations.

> As it is, there are some programs that call a lot of shell
> commands that I write in sh instead of Ruby, and where I'd really like
> to do them in Ruby.

Depending on what you do, you might notice that you don't need those shell
programs for the job. For example, "cat" is easily done with File.open()
{|io|...} and "rm" can be taken care of by File.delete().

I know, but again: This does not handle the cases I'm interested in.

> The starting point I see for something like this would be to override
> method_missing like above, but make it return an object where | is
> overridden, and that have handling of shell return codes.
>
> The challenges I see here is
> - It's not possible to override the trueness/falseness of an object,
> so we'd need to call a special method to find out if a command failed
> or passed
> - It is hard to implement -e (give an error if a complete shell line
> fails - but not if we have an fail || true). Maybe trace_func could
> be of help here, though.

I'm not sure whether I wanted Ruby scripts to look similar to shell
scripts or whether it's feasible to a degree that is satisfactory.

I don't want all Ruby programs to look like shell scripts. However, I
find the shell script syntax very convenient for some types of
operations - more convenient than Ruby for programs where the chief
operations are running external commands with pipes and filters. I
would like to be able to embed this into Ruby programs, and easily
convert this kind of program from a shell script to Ruby for further
massaging.

So yes, I really want an sh-like syntax inside my Ruby scripts - not
for everything, but for the cases where I presently end up using sh
because Ruby is inconvenient.

I wouldn't mind having a method pipe(*commands) in Kernel or IO that starts
all these commands in parallel and connects them via pipes.

Intriguing idea. I'd use an array per command instead of a string (to
avoid white space parsing issues), but apart from that I like it :slight_smile:

It isn't quite what I'm thinking of, but it is more useful for the
general case. (I was thinking of something for very special cases,
only usable inside particular blocks.)

Eivind.

···

On Sat, 2 Oct 2004 00:09:59 +0900, Robert Klemme <bob.news@gmx.net> wrote:

do you just want pipes & filters but for ruby?
if so, look back on some of my old emails here w/ jim weirich about
dataflow and generators.
jim is my hero. :smiley:

-z

···

On Sat, 2 Oct 2004 04:30:58 +0900, Eivind Eklund <eeklund@gmail.com> wrote:

On Sat, 2 Oct 2004 00:09:59 +0900, Robert Klemme <bob.news@gmx.net> wrote:
>
> "Eivind Eklund" <eeklund@gmail.com> schrieb im Newsbeitrag
> news:dc9b20bb041001065332408f65@mail.gmail.com...
>
> > On the subject (if not the Subject:): Have anybody played with make it
> > possible to use Ruby for running sort-of shell scripts?
>
> This topic arises from time to time. AFAIR there are IRB extensions that
> make IRB shell-like.

I'm not thinking of IRB - I'm thinking of scripting specifically.

> > Ie, including
> > pipes etc.
>
> IO.popen() uses pipes internally. And I think there is also another
> method.

Yes, but these are highly clumsy when doing complex operations.

> > As it is, there are some programs that call a lot of shell
> > commands that I write in sh instead of Ruby, and where I'd really like
> > to do them in Ruby.
>
> Depending on what you do, you might notice that you don't need those shell
> programs for the job. For example, "cat" is easily done with File.open()
> {|io|...} and "rm" can be taken care of by File.delete().

I know, but again: This does not handle the cases I'm interested in.

> > The starting point I see for something like this would be to override
> > method_missing like above, but make it return an object where | is
> > overridden, and that have handling of shell return codes.
> >
> > The challenges I see here is
> > - It's not possible to override the trueness/falseness of an object,
> > so we'd need to call a special method to find out if a command failed
> > or passed
> > - It is hard to implement -e (give an error if a complete shell line
> > fails - but not if we have an fail || true). Maybe trace_func could
> > be of help here, though.
>
> I'm not sure whether I wanted Ruby scripts to look similar to shell
> scripts or whether it's feasible to a degree that is satisfactory.

I don't want all Ruby programs to look like shell scripts. However, I
find the shell script syntax very convenient for some types of
operations - more convenient than Ruby for programs where the chief
operations are running external commands with pipes and filters. I
would like to be able to embed this into Ruby programs, and easily
convert this kind of program from a shell script to Ruby for further
massaging.

So yes, I really want an sh-like syntax inside my Ruby scripts - not
for everything, but for the cases where I presently end up using sh
because Ruby is inconvenient.

> I wouldn't mind having a method pipe(*commands) in Kernel or IO that starts
> all these commands in parallel and connects them via pipes.

Intriguing idea. I'd use an array per command instead of a string (to
avoid white space parsing issues), but apart from that I like it :slight_smile:

It isn't quite what I'm thinking of, but it is more useful for the
general case. (I was thinking of something for very special cases,
only usable inside particular blocks.)

Eivind.

If it's just external commands you're running, linking them together with
stdout/stdin, then you can still just do

   a = `ls | grep a*`
or
   system("ls | grep *")

i.e. let the shell do what it's good at. Might not work if you're running
under a system which doesn't have a shell though.

Regards,

Brian.

···

On Sat, Oct 02, 2004 at 04:30:58AM +0900, Eivind Eklund wrote:

I don't want all Ruby programs to look like shell scripts. However, I
find the shell script syntax very convenient for some types of
operations - more convenient than Ruby for programs where the chief
operations are running external commands with pipes and filters. I
would like to be able to embed this into Ruby programs

"Eivind Eklund" <eeklund@gmail.com> schrieb im Newsbeitrag
news:dc9b20bb04100112302938e85f@mail.gmail.com...

>
> "Eivind Eklund" <eeklund@gmail.com> schrieb im Newsbeitrag
> news:dc9b20bb041001065332408f65@mail.gmail.com...
>
> > On the subject (if not the Subject:): Have anybody played with make

it

> > possible to use Ruby for running sort-of shell scripts?
>
> This topic arises from time to time. AFAIR there are IRB extensions

that

> make IRB shell-like.

I'm not thinking of IRB - I'm thinking of scripting specifically.

> > Ie, including
> > pipes etc.
>
> IO.popen() uses pipes internally. And I think there is also another
> method.

Yes, but these are highly clumsy when doing complex operations.

> > As it is, there are some programs that call a lot of shell
> > commands that I write in sh instead of Ruby, and where I'd really

like

> > to do them in Ruby.
>
> Depending on what you do, you might notice that you don't need those

shell

> programs for the job. For example, "cat" is easily done with

File.open()

> {|io|...} and "rm" can be taken care of by File.delete().

I know, but again: This does not handle the cases I'm interested in.

> > The starting point I see for something like this would be to

override

> > method_missing like above, but make it return an object where | is
> > overridden, and that have handling of shell return codes.
> >
> > The challenges I see here is
> > - It's not possible to override the trueness/falseness of an object,
> > so we'd need to call a special method to find out if a command

failed

> > or passed
> > - It is hard to implement -e (give an error if a complete shell line
> > fails - but not if we have an fail || true). Maybe trace_func could
> > be of help here, though.
>
> I'm not sure whether I wanted Ruby scripts to look similar to shell
> scripts or whether it's feasible to a degree that is satisfactory.

I don't want all Ruby programs to look like shell scripts. However, I
find the shell script syntax very convenient for some types of
operations - more convenient than Ruby for programs where the chief
operations are running external commands with pipes and filters. I
would like to be able to embed this into Ruby programs, and easily
convert this kind of program from a shell script to Ruby for further
massaging.

So yes, I really want an sh-like syntax inside my Ruby scripts - not
for everything, but for the cases where I presently end up using sh
because Ruby is inconvenient.

I'm not sure whether it's possible to reach the level of conformance that
you're aiming at. I personally have no problem to use shell scripts for
certain tasks and ruby scripts for others. Maybe it turns out that ruby
is just not the appropriate tool for the task.

> I wouldn't mind having a method pipe(*commands) in Kernel or IO that

starts

> all these commands in parallel and connects them via pipes.

Intriguing idea. I'd use an array per command instead of a string (to
avoid white space parsing issues), but apart from that I like it :slight_smile:

It isn't quite what I'm thinking of, but it is more useful for the
general case. (I was thinking of something for very special cases,
only usable inside particular blocks.)

Well, or a combination as with system today:

IO.pipe( "ls -laF", %w{grep -v bar}, ["wc", "-l"]) do |io|
  while (l=io.gets)
    puts l
  end
end

Kind regards

    robert

···

On Sat, 2 Oct 2004 00:09:59 +0900, Robert Klemme <bob.news@gmx.net> wrote: