From: Robert Date: 2003-05-03T02:07:21+09:00 Subject: Re: temporary redirection of stdout "ahoward" schrieb im Newsbeitrag news:Pine.LNX.4.53.0305021534540.25362@eli.fsl.noaa.gov... > i am more confused than usual ;-) I seems so... :-) > ~ > cat foo.rb > #!/usr/bin/env ruby > > def dump s, binding=nil > case s > when Symbol > STDERR.puts %Q(\t#{s} => #{eval(s.to_s, binding).inspect}) > when String > STDERR.puts "\t#{s}" > end > end > > File.open("output","w") { |f| > > dump '(ORIGINAL)' > [:f,:$defout,:$stdout,:STDOUT].map{|sym| dump sym, binding} > > puts("To the screen") > > $defout.reopen f > dump '(REDIRECTED TO FILE)' > [:f,:$defout,:$stdout,:STDOUT].map{|sym| dump sym, binding} > > puts("To the file") > > $defout.reopen STDOUT > dump '(RESTORED)' > [:f,:$defout,:$stdout,:STDOUT].map{|sym| dump sym, binding} > > > puts("To the screen again") > } > > > > ruby foo.rb > (ORIGINAL) > f => # > $defout => # > $stdout => # > STDOUT => # > To the screen > (REDIRECTED TO FILE) > f => # > $defout => # > $stdout => # > STDOUT => # > (RESTORED) > f => # > $defout => # > $stdout => # > STDOUT => # > > > so it appears that reopening even $defout results in STDOUT and $stdout also > being reopened to point to a file. in otherwords, you will never be able to > restore unless a copy is made prior to this. this works like it reads: Err, why are you surprised? This is exactly what I would have expected since $defout, $stdout and STDOUT initially point to the same instance. So it doesn't really matter on which of the instances you do issue 'reopen', they "all" get redirected. Redirecting should be done by assignment: File.open("output","w") do |f| old_defout = $defout begin puts "to the screen" # redirect $defout = f puts "to the file" ensure $defout = old_defout end end This is much simpler than your solution and works without adding code to IO classes: > > cat redirect.rb && ruby redirect.rb && echo 'output:' && cat output > #!/usr/bin/env ruby > > class IO > def redirect io > (@__self ||= []) << (clone = self.clone) > reopen io > clone > end > def restore > raise 'NOT REDIRECTED' unless > defined? @__self and not @__self.empty? > reopen @__self.pop > end > end > > File.open("output","w") { |f| > puts("To the screen") > > STDOUT.redirect f > puts("To the file") > > STDOUT.restore > puts("To the screen again") > } > > To the screen > To the screen again > output: > To the file Regards robert