Erik =?ISO-8859-1?Q?B=E5gfors?= <erik / bagfors.nu> wrote: > On 17 Jul 2001 19:55:19 +0900, Steve Hill wrote: > > Hi, > > I'm sure this isn't really a ruby specific question, but since I scipt > > in ruby, maybe someone has a good answer... > > > > Some of the scripting relies on some of the standard unix tools to do > > its work, called using backquotes. e.g. the following facet which > > processes the columns of a file previously created with grep. > > > > `grep FOO foo.txt > foo.tmp` > > > > flag?=false > > hash=Hash.new > > IO.for_each("foo.tmp") do |line| > > unless flag? do > > cols=line.split > > (0...cols).each {|i| hash[i]=Bar.new} > > end > > > > cols=line.split > > hash.each {|k,v| v.process(cols[i]) } #A > > end > > > > The problem is that the script may fail at the line marked A because > > the file "foo.tmp" has either not been written at all, or has not been > > completely written. > > > > The first problem can be solved by inserting the following section > > after the grep. > > > > while !File.stat?("foo.tmp").size? > > sleep 0.001 > > end > > > > Does anyone know how to test that "foo.tmp" has been completely > > written? > > > > Don't write to a file. Write to the program instead. Something like > this I think: > > IO.popen("grep FOO foo.txt").each do |line| > # do stuff with |line| > end Better yet, do all of the processing in pure Ruby and get much lower overhead. A fork and exec and a bunch of reads and writes and more reads is a lot more than just doing the same in Ruby. I like to use more verbose syntax than many: lines = [] File.open("foo.txt", "r") {|file| file.each_line {|line| if line =~ /FOO/ lines.push(line) end } } Alternatively, to have it read the whole file into memory before processing it: lines = File.open("foo.txt", "r") {|file| file.readlines.grep(/FOO/)} or some shorter alternative thereof using newer mechanisms like File.readline. You could even create a method to make things even easier: class << File unless defined?(grep) def grep(filename, regex, can_fail = true) lines = [] begin File.open(filename, "r") {|file| file.each_line {|line| lines.push(line) if line =~ regex } } rescue SystemCallError => e raise(e) if can_fail end lines end end end Then you'd be able to do: lines = File.grep("foo.txt", /FOO/, false) # here, returns [] on failure # instead of raising an exception -- Brian Fundakowski Feldman \ FreeBSD: The Power to Serve! / green / FreeBSD.org `------------------------------'