From: Robert Klemme Date: 2008-01-20T20:54:58+09:00 Subject: Re: Timeout error using Find module On 19.01.2008 22:53, Mike -- wrote: > I'm relatively new to Ruby, and am loving it! However, I'm getting some > trouble trying to implement a simple search application. The idea is to > search a directory (specified by the user) for a given reg. expression > in the filename (again specified by the user). Easy, really. > > This works fine for the most part, but if I choose to search from the > root directory, I get a operation timeout error like so: > > /usr/local/lib/ruby/1.8/find.rb:43:in `open': Operation timed out - > /net/broadcasthost (Errno::ETIMEDOUT) > from /usr/local/lib/ruby/1.8/find.rb:43:in `find' > from /usr/local/lib/ruby/1.8/find.rb:38:in `catch' > from /usr/local/lib/ruby/1.8/find.rb:38:in `find' > from ruby_find3.rb:10 > > I'm a little confused as to why it would timeout if it's simply > traversing the local directory tree? I would be grateful if anyone would > be able to give any assistance - I'm sure it's probably a simple fix! From what you write I assume you are on a Unix style operating system (single root directory). As the stack trace seems to reveal there is some network communication going on ("/net/broadcasthost"). Apparently there are some network drives mounted. Since you start in the root directory they will be visited eventually. You can check with "mount" or "df" what file systems are mounted on your system. > Apologies if something like this has been discussed already...I have had > a look at some forum posts and have only been able to find > server-related timeout threads so far. I did learn about rescuing these > timeout errors from some threads, which I had a stab at implementing > briefly at the end. > > Here's my code: > > ========================== > require 'find' > path = gets.chomp > search1 = gets.chomp > search_exp = Regexp.new(search1, Regexp::IGNORECASE) > > puts "<<-- Beginning Search -->>" > > begin > Find.find(path) do |p| > if FileTest.directory?(p) > if File.basename(p) =~ search_exp > puts "Dir: " + File.basename(p) > > # Ignore directories beginning with "." This is completely superfluous because Find.find takes care of that (if it would not it would *always* enter an infinite loop). > elsif File.basename(p)[0] == ?. > Find.prune > end > end > > if FileTest.file?(p) > if (File.basename(p) =~ search_exp) > puts File.basename(p) + " : " + File.expand_path(p) > elsecat > Find.prune Why do you prune here? What this basically means is that traversal will stop on every directory that contains at least one file name that does not match your regexp. Is this really what you want? > end > end > end > rescue SystemCallError > puts "Timeout error :S" > end > > puts "<<-- End of Search -->" Is this really the exact code that produced the error you present above? I ask because you do not print out the exception itself but rather the fixed string "Timeout error :S". Some additional remarks: I usually try to avoid local variable 'p' because of the method 'p' (print out #inspect string of an object) which I frequently use for debugging. You can make your code a bit more efficient by not repeating tasks, namely the basename extraction. This is how I would probably do it - assuming you want to find all files and directories where the basename matches the given regexp. require 'find' dir = ARGV.shift or raise "Need a directory name" rx = Regexp.new((ARGV.shift or raise "Need a regexp"), Regexp::IGNORECASE) Find.find dir do |f| if rx =~ File.basename(f) print File.directory?(f) ? "Dir : " : "File: ", f, "\n" end end Kind regards robert