irb: a great tool in it's own right

P

Phil Tomson

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
 
R

rcoder

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.
 
K

Kaspar Schiess

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

(e-mail address removed) 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
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (MingW32)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFBXT6LFifl4CA0ImQRAnu6AJ0VTbEqWBuTT4RQ9C0jJn1olyLhhgCfQeUe
SClEUPHO1hz0vL1YV/M6qlE=
=9O4G
-----END PGP SIGNATURE-----
 
K

Kaspar Schiess

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

And

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

might be considered more useful by some.

best regards,
kaspar
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (MingW32)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFBXUDmFifl4CA0ImQRAkK4AJ98YaDtqsmUIANNI5ZUnSKVZ6GN/QCeLH5e
KX+qvlpr7IDbsHKhRxqBlzs=
=etgH
-----END PGP SIGNATURE-----
 
B

Brian Candler

Just in case anyone is really interested, the def is

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

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.
 
T

trans. (T. Onoma)

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

(e-mail address removed) 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

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.
 
B

Brian Candler

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

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.
 
E

Eivind Eklund

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.
 
R

Robert Klemme

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
 
E

Eivind Eklund

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.
IO.popen() uses pipes internally. And I think there is also another
method.

Yes, but these are highly clumsy when doing complex operations.
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.
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 :)

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.
 
A

Andrew Johnson

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
 
Z

zuzu

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. :D

-z
 
B

Brian Candler

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

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.
 
R

Robert Klemme

Eivind Eklund said:
I'm not thinking of IRB - I'm thinking of scripting specifically.


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


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


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.
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 :)

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,150
Latest member
MakersCBDReviews
Top