From: Robert Klemme Date: 2003-10-06T17:40:32+09:00 Subject: Re: backquotes, system, shell and ruby "John Carter" 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