I have come up with a little script that works well in IRB for issuing 
shell commands and piping them together. For example

	require './shell.rb'

	io = Sh.ls("/bin").grep("grep")
	puts io

generates

	
	bzegrep
	bzfgrep
	bzgrep
	egrep
	fgrep
	grep
	zegrep
	zfgrep
	zgrep

I am curious as to whether the way I have implemented it is the best 
way. It seems kind of clunky to me. I have to spawn a new Ruby process 
using fork and then reopen $stdin on the child process and connect it
to the output stream of the previous command. I was hoping to find
a way to get around forking ruby processes to do this. Any
ideas

The source code is below or syntax highlighted here
http://xtargets.com/snippets/posts/show/77

Brad

--------------------------------

module Sh
     class Command

         def initialize(cmd, *args)
             @cmd = cmd
             @args = args
             @io = nil
         end

         def inspect
             to_s
         end

         def to_str
             to_s
         end

         def to_s
             call
             str = @io.read
             @io.close
             str
         end

         def | other
             call
             other.call(@io)
         end

         def method_missing(name, *args)
             self | Command.new(name, *args)
         end

         def call (io=nil)

             # The @io object can only be assigned
             # once
             return self if @io

             command =  @cmd.to_s + " " + @args.join(" ")

             if io
                 #  We need a new process
                 #  and a pipe to connect the
                 #  this command to the previous
                 #  command in the chain.
                 rd, wr = IO.pipe

                 if fork
                     # Parent
                     wr.close
                 else
                     # Child
                     rd.close
                     begin
                         # Reconnect the STDIN of the
                         # new process to the io parameter
                         $stdin.reopen(io)
                         IO.popen command do |f|
                             while txt = f.read(4096)
                                 wr.write txt
                             end
                         end
                     rescue Errno::EPIPE
                         # Ignore the broken pipe
                         # cause the other process
                         # has thrown away the pipe
                         # earlier than we used outs
                     ensure
                         wr.close
                     end
                     exit
                 end
                 @io = rd
             else
                 # This command is executed standalone.
                 @io = IO.popen command
             end
             self
         end
     end

     def self.method_missing (name, *args)
         Command.new(name, *args)
     end
end