Tag unstable CGI specs.
[rbx.git] / lib / find.rb
blob0d22dd62d630f616bee7368726bbad2cbd30b64b
2 # find.rb: the Find module for processing all files under a given directory.
6 # The +Find+ module supports the top-down traversal of a set of file paths.
8 # For example, to total the size of all files under your home directory,
9 # ignoring anything in a "dot" directory (e.g. $HOME/.ssh):
11 #   require 'find'
13 #   total_size = 0
15 #   Find.find(ENV["HOME"]) do |path|
16 #     if FileTest.directory?(path)
17 #       if File.basename(path)[0] == ?.
18 #         Find.prune       # Don't look any further into this directory.
19 #       else
20 #         next
21 #       end
22 #     else
23 #       total_size += FileTest.size(path)
24 #     end
25 #   end
27 module Find
29   #
30   # Calls the associated block with the name of every file and directory listed
31   # as arguments, then recursively on their subdirectories, and so on.
32   #
33   # See the +Find+ module documentation for an example.
34   #
35   def find(*paths) # :yield: path
36     paths.collect!{|d| d.dup}
37     while file = paths.shift
38       catch(:prune) do
39         yield file.dup.taint
40         next unless File.exist? file
41         begin
42           if File.lstat(file).directory? then
43             d = Dir.open(file)
44             begin
45               for f in d
46                 next if f == "." or f == ".."
47                 if File::ALT_SEPARATOR and file =~ /^(?:[\/\\]|[A-Za-z]:[\/\\]?)$/ then
48                   f = file + f
49                 elsif file == "/" then
50                   f = "/" + f
51                 else
52                   f = File.join(file, f)
53                 end
54                 paths.unshift f.untaint
55               end
56             ensure
57               d.close
58             end
59           end
60         rescue Errno::ENOENT, Errno::EACCES
61         end
62       end
63     end
64   end
66   #
67   # Skips the current file or directory, restarting the loop with the next
68   # entry. If the current file is a directory, that directory will not be
69   # recursively entered. Meaningful only within the block associated with
70   # Find::find.
71   #
72   # See the +Find+ module documentation for an example.
73   #
74   def prune
75     throw :prune
76   end
78   module_function :find, :prune
79 end