[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

backquotes, system, shell and ruby

John Carter

10/3/2003 1:17:00 AM

6 Answers

Ryan Pavlik

10/3/2003 1:38:00 AM

0

On Fri, 3 Oct 2003 10:16:53 +0900
John Carter <john.carter@tait.co.nz> wrote:

> Somebody suggested I use zsh instead of bash for my commandline, so I
> looked at it, looked at the syntax for tweaking the profile files, and
> said...
> "Yuck! Another badly designed syntax! Why can't I just use Ruby?"

It's sh. Deal with it. ;-) It's not great, but it's not so bad,
either. I would, however, not mind having a ruby shell. But I also
don't expect to use ruby---which is designed to be suitable primarily
as a programming language---to *directly* fit the bill.

> And that got me thinking.
>
> Consider backquotes.
<snip>
> Why? Why does a scripting language like Ruby keep invoking an old and bad
> scripting language call shell?

I'm not sure what you're getting at here. Yes, it ran a shell,
because that's what system() does. You can even do it in C, although
C doesn't use backticks as a shorthand.

> Because...
>
> a) Ruby doesn't have a good syntax for invoking and dealing with
> processes and pipes between processes.

You mean like File.popen?

> b) Ruby doesn't have a built in understanding of ENV['PATH']

The OS understands the path for you. Ruby doesn't need to.

> c) Ruby doesn't have such a simple syntax for globbing (beyond
> Dir['*.c'])

Ruby isn't a shell, either, and although it is a scripting language
(which explains the presence of ``), this doesn't automatically make
it suitable for a drop-in shell replacement.

> Consider the "rename" facility that comes with perl these days.
<snip>
> Ooh! Looky! Nice! Wouldn't it be nice to have the power of ruby
> intertwingled with the commandline.

At times I fire up irb to take care of similar complex tasks.

> Ruby does have Shell.rb, which takes us halfway there. (If it had
> decent docs...)
>
> How hard would it be to extend the backtick syntax to be a pure ruby
> thing. ie. So proc_exec doesn't invoke bash, but invokes Shell.rb?
>
>
> Hmm. Could we even do this entirely in UserLand? ie. Couldn't we
> override proc_exec and replace it with ruby code that parses the
> string, handles the redirects, variable interpolation quoting and
> forks, then just directly execs the program without ever touching sh?

What you need to do is simply write a shell that uses ruby instead of
its own sh-like syntax. Modifying ruby is not the answer. Using ruby
and a little readline loop with some decent parsing (calls to fork,
popen, etc.: process and IPC handling) is.

I must say I have wanted something like this for awhile. I even came
up with a really nice syntax for integrating shell commands and ruby,
although I forget off the top of my head what it was... it'd be
_fairly_ easy to do.

Just don't try to modify ruby to do it, because it's not the right
solution.

--
Ryan Pavlik <rpav@mephle.com>

"Well what was it, Mr. Nightmare Pants?" - 8BT

Harry Ohlsen

10/3/2003 1:55:00 AM

0

John Carter wrote:

> a = `wc *.c`
>
> What did that do? Same as open("|wc *.c").
>
> It ran bash!
>
> Yuck!
>
> system( "tar -xvzf foo.tgz foo")
>
> What did that do? It ran shell!
>
> Why? Why does a scripting language like Ruby keep invoking an old and bad
> scripting language call shell?

I think it sits in the "it's the easiest thing to to do" basket.

> Consider the "rename" facility that comes with perl these days.
> For example, to rename all files matching "*.bak" to strip the exten-
> sion, you might say
>
> rename 's/\.bak$//' *.bak
>
> To translate uppercase names to lower, you'd use
>
> rename 'y/A-Z/a-z/' *

Something like that would be quite nice, since it's a pain in the butt to do with most shells ... strangely, this is one of the few things that DOS has done nicely for about ten years.

Of course, it's pretty easy to do in Ruby already (warning: totally untested) ...

Dir["*.bak"].each do |file|
File.rename file, file.sub(/\.bak$/, "")
end

or maybe

def rename(wildcard, &block)
Dir[wildcard].each do |file|
File.rename file, (yield file)
end
end

rename("*.bak") {|f| f.sub(/\.bak$/, "")}

> How hard would it be to extend the backtick syntax to be a pure ruby
> thing. ie. So proc_exec doesn't invoke bash, but invokes Shell.rb?

I guess it comes down to how much of the shell syntax you want to parse. While it's not hideously complex, sh/bash syntax is quite a funny grammar. I guess handling just globbing, pipes and redirection would be enough to make this useful, though.

The other issue, I would imagine, is *which* shell's syntax to use. I've never needed to know, so I've not looked, but I assume both system() and backticks just end up calling the C system() library routine, which means that the shell invoked is effectively user-defined.

Cheers,

Harry O.



Sean O'Dell

10/3/2003 4:28:00 AM

0

John Carter wrote:
> Somebody suggested I use zsh instead of bash for my commandline, so I
> looked at it, looked at the syntax for tweaking the profile files, and
> said...
> "Yuck! Another badly designed syntax! Why can't I just use Ruby?"
>
> And that got me thinking.
>
> Consider backquotes.
>
> a = `wc *.c`
>
> What did that do? Same as open("|wc *.c").
>
> It ran bash!
>
> Yuck!
>
> system( "tar -xvzf foo.tgz foo")
>
> What did that do? It ran shell!
>
> Why? Why does a scripting language like Ruby keep invoking an old and bad
> scripting language call shell?

A script language, if it wants to be portable, doesn't "blend" itself
with unix shell programs. Ruby has pipes, sockets and other perfectly
normal programatic ways to communicate between applications.

> Because...
>
> a) Ruby doesn't have a good syntax for invoking and dealing with
> processes and pipes between processes.

It has the IO::pipe method which is pretty standard. You create a pair
of pipes, then fork and exec whatever program you want to communicate with.

> b) Ruby doesn't have a built in understanding of ENV['PATH']

Well, PATH isn't really for programming languages; it's a shell/os
paradigm. Programs *can* make use of it, if they choose to, but I don't
see that as being a languages' responsibility. It's there in the ENV
hash; use it if you need it.

Anyway, it would be pretty simple to implement, and I wouldn't be
surprised if there isn't support for finding programs with it buried
somewhere in one of the libraries distributed with it.

> c) Ruby doesn't have such a simple syntax for globbing (beyond
> Dir['*.c'])
>
> Consider the "rename" facility that comes with perl these days.
> For example, to rename all files matching "*.bak" to strip the exten-
> sion, you might say
>
> rename 's/\.bak$//' *.bak
>
> To translate uppercase names to lower, you'd use
>
> rename 'y/A-Z/a-z/' *
>
> Ooh! Looky! Nice! Wouldn't it be nice to have the power of ruby
> intertwingled with the commandline.

I would write:

Dir["*.bak"].each{|f| File::rename(f, f.gsub(/\.bak$/, "")) }

and:

Dir["*"].each{|f| File::rename(f, f.gsub(/[a-z]/){|s| s.upcase}) }

Wordy, but it should work just fine.

Anyway, Ruby isn't a shell, it's a programming language.

> Ruby does have Shell.rb, which takes us halfway there. (If it had
> decent docs...)
>
> How hard would it be to extend the backtick syntax to be a pure ruby
> thing. ie. So proc_exec doesn't invoke bash, but invokes Shell.rb?
>
> Hmm. Could we even do this entirely in UserLand? ie. Couldn't we
> override proc_exec and replace it with ruby code that parses the
> string, handles the redirects, variable interpolation quoting and
> forks, then just directly execs the program without ever touching sh?

I personally don't think it's Ruby's job to be more like a shell.
Shells do that very well already. Besides, no matter how much you
modified Ruby to make it more shell-like, you are always going to find
things it won't do as well as a shell could, so you will drop out and
ask the shell to do it.

Using a programming language, as opposed to a shell, means that some
things are easier to do, and some things are harder. But I don't think
changing Ruby to make a specific group of tasks easier, when shells
already do those tasks very well, is the answer.

Sean O'Dell


Eric Hodel

10/3/2003 5:19:00 AM

0

John Carter (john.carter@tait.co.nz) wrote:

> Consider backquotes.
>
> a = `wc *.c`
>
> What did that do? Same as open("|wc *.c").
>
> It ran bash!
>
> Yuck!
>
> system( "tar -xvzf foo.tgz foo")
>
> What did that do? It ran shell!
>
> Why? Why does a scripting language like Ruby keep invoking an old and bad
> scripting language call shell?

Because that's what system(3) does, check the man page.

Perl does it, and if I had a Python installed, I bet python would do it
too. If you want it to not run in a shell, use fork and exec.

--
Eric Hodel - drbrain@segment7.net - http://se...
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

dagbrown

10/4/2003 2:37:00 AM

0

In article <Pine.LNX.4.58.0310031253560.10643@parore.tait.co.nz>,
John Carter <john.carter@tait.co.nz> wrote:
: Somebody suggested I use zsh instead of bash for my commandline, so I
: looked at it, looked at the syntax for tweaking the profile files, and
: said...
: "Yuck! Another badly designed syntax! Why can't I just use Ruby?"
:
: And that got me thinking.
:
: Consider backquotes.
:
: a = `wc *.c`
:
: What did that do? Same as open("|wc *.c").
:
: It ran bash!
:
: Yuck!
:
: system( "tar -xvzf foo.tgz foo")
:
: What did that do? It ran shell!

So, er...

Give it a list instead!

irb(main):012:0> system("echo $PPID")
16554
=> true
irb(main):013:0> system("echo","$PPID")
$PPID
=> true

The second version has not been touched by a shell of any kind.
Cool, huh?

: Why? Why does a scripting language like Ruby keep invoking an old and bad
: scripting language call shell?
:
: Because...

....you keep telling it to!

"Doctor, it hurts when I do this!" "Well, stop doing that then."

--Dave
--
"Kids have it easy today. All they have to listen to is stories about
how back in the '70s we had to listen to stories about how bad it was
back in the '30s."
-- Keith Lynch

Robert Klemme

10/6/2003 8:36:00 AM

0


"John Carter" <john.carter@tait.co.nz> schrieb im Newsbeitrag
news:Pine.LNX.4.58.0310031253560.10643@parore.tait.co.nz...
> Somebody suggested I use zsh instead of bash for my commandline, so I
> looked at it, looked at the syntax for tweaking the profile files, and
> said...
> "Yuck! Another badly designed syntax! Why can't I just use Ruby?"
>
> And that got me thinking.
>
> Consider backquotes.
>
> a = `wc *.c`
>
> What did that do? Same as open("|wc *.c").
>
> It ran bash!
>
> Yuck!
>
> system( "tar -xvzf foo.tgz foo")
>
> What did that do? It ran shell!
>
> Why? Why does a scripting language like Ruby keep invoking an old and
bad
> scripting language call shell?
>
> Because...

.... you did not invoke it with an array.

> a) Ruby doesn't have a good syntax for invoking and dealing with
> processes and pipes between processes.
>
> b) Ruby doesn't have a built in understanding of ENV['PATH']
>
> c) Ruby doesn't have such a simple syntax for globbing (beyond
> Dir['*.c'])

???

ruby -e 'p Dir["/cygdrive/c/temp/ruby/*.{rb,bak}"]'
ruby -e 'p Dir["/cygdrive/c/temp/**.{rb,bak}"]'

That's quite powerful and simple.

> Consider the "rename" facility that comes with perl these days.
> For example, to rename all files matching "*.bak" to strip the
exten-
> sion, you might say
>
> rename 's/\.bak$//' *.bak

ruby -e 'Dir["*.bak"].each {|f| File.rename(f, f.gsub(/\.bak$/, ""))}'

> To translate uppercase names to lower, you'd use
>
> rename 'y/A-Z/a-z/' *

ruby -e 'Dir["*"].each {|f| File.rename(f, f.upcase)}'
ruby -e 'Dir["*"].each {|f| File.rename(f, f.tr("a-z", "A-Z"))}'

> Ooh! Looky! Nice! Wouldn't it be nice to have the power of ruby
> intertwingled with the commandline.
>
>
> Ruby does have Shell.rb, which takes us halfway there. (If it had
> decent docs...)
>
> How hard would it be to extend the backtick syntax to be a pure ruby
> thing. ie. So proc_exec doesn't invoke bash, but invokes Shell.rb?
>
>
> Hmm. Could we even do this entirely in UserLand? ie. Couldn't we
> override proc_exec and replace it with ruby code that parses the
> string, handles the redirects, variable interpolation quoting and
> forks, then just directly execs the program without ever touching sh?

We could - but I wouldn't make this the default since every shell has it's
own pecularities (i.e. different syntax and built in commands. Why not
simply write a method that takes a string and returns an array processed
according to a particular shell convention? Then you can do

system( bashParse( "ls -lf *.bak" ) )

which is quite simple IMHO.

But I would leave in the default shell invocation because that gives most
flexibility.

Regards

robert