--nextPart2082345.jyFlp0tXVb
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

On Thursday 06 September 2007 11:35:05 pm Brad Phelan wrote:
> I have come up with a little script that works well in IRB for issuing=20
> shell commands and piping them together. For example
>=20
> 	require './shell.rb'
>=20
> 	io =3D Sh.ls("/bin").grep("grep")
> 	puts io
>=20
> generates
>=20
> =09
> 	bzegrep
> 	bzfgrep
> 	bzgrep
> 	egrep
> 	fgrep
> 	grep
> 	zegrep
> 	zfgrep
> 	zgrep
>=20
> I am curious as to whether the way I have implemented it is the best=20
> way. It seems kind of clunky to me. I have to spawn a new Ruby process=20
> 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
>=20
> The source code is below or syntax highlighted here
> http://xtargets.com/snippets/posts/show/77
>=20
> Brad
>=20
> --------------------------------
>=20
> module Sh
>      class Command
>=20
>          def initialize(cmd, *args)
>              @cmd =3D cmd
>              @args =3D args
>              @io =3D nil
>          end
>=20
>          def inspect
>              to_s
>          end
>=20
>          def to_str
>              to_s
>          end
>=20
>          def to_s
>              call
>              str =3D @io.read
>              @io.close
>              str
>          end
>=20
>          def | other
>              call
>              other.call(@io)
>          end
>=20
>          def method_missing(name, *args)
>              self | Command.new(name, *args)
>          end
>=20
>          def call (io=3Dnil)
>=20
>              # The @io object can only be assigned
>              # once
>              return self if @io
>=20
>              command =3D  @cmd.to_s + " " + @args.join(" ")
>=20
>              if io
>                  #  We need a new process
>                  #  and a pipe to connect the
>                  #  this command to the previous
>                  #  command in the chain.
>                  rd, wr =3D IO.pipe
>=20
>                  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 =3D 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 =3D rd
>              else
>                  # This command is executed standalone.
>                  @io =3D IO.popen command
>              end
>              self
>          end
>      end
>=20
>      def self.method_missing (name, *args)
>          Command.new(name, *args)
>      end
> end

Stdlib shell (require 'shell') does much of that IIRC.
( http://ruby-doc.org/stdlib/libdoc/shell/rdoc/classes/Shell.html )

=2D-=20
Konrad Meyer <konrad / tylerc.org> http://konrad.sobertillnoon.com/

--nextPart2082345.jyFlp0tXVb
Content-Type: application/pgp-signature; name=signature.asc 
Content-Description: This is a digitally signed message part.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQBG4PUkCHB0oCiR2cwRAqxLAJ4vPkcPTy+CC1aEh68MQszgOh3d2QCdEh6x
6QJV6Otl20G4EHZlFUCQOhU=
=wE3f
-----END PGP SIGNATURE-----

--nextPart2082345.jyFlp0tXVb--