class Dir
Public Class Methods
Ascend a directory path.
a = [] Dir.ascend("/var/log") do |path| a << path end a #=> ['/var/log', '/var', '/']
CREDIT: Daniel Berger, Jeffrey Schwab
TODO: make it work with windows too use FileTest#root?
# File lib/facets/dir/ascend.rb, line 20 def self.ascend(dir, inclusive=true, &blk) dir = dir.dup blk.call(dir) if inclusive ri = dir.rindex('/') while ri dir = dir.slice(0...ri) if dir == "" blk.call('/') ; break end blk.call( dir ) ri = dir.rindex('/') end end
Descend a directory path.
d = [] Dir.descend("/var/log") do |path| d << path end d #=> ['/', '/var', '/var/log']
CREDIT: Daniel Berger, Jeffrey Schwab
# File lib/facets/dir/ascend.rb, line 46 def self.descend(path) #:yield: paths = path.split('/') paths.size.times do |n| pth = File.join(*paths[0..n]) pth = "/" if pth == "" yield(pth) end end
Same as Dir#recurse.
# File lib/facets/dir/recurse.rb, line 30 def self.ls_r(path='.', &block) recurse(path, &block) end
Like glob
but can take multiple patterns.
Dir.multiglob('tmp .rb', 'tmp/*.py')
Rather then constants for options multiglob accepts a trailing options hash of symbol keys…
:noescape File::FNM_NOESCAPE :casefold File::FNM_CASEFOLD :pathname File::FNM_PATHNAME :dotmatch File::FNM_DOTMATCH :strict File::FNM_PATHNAME && File::FNM_DOTMATCH
It also has an option for recurse…
:recurse Recurively include contents of directories.
For example
Dir.multiglob('tmp/*', :recurse => true)
would have the same result as
Dir.multiglob('tmp/ *')
# File lib/facets/dir/multiglob.rb, line 28 def self.multiglob(*patterns) options = (Hash === patterns.last ? patterns.pop : {}) if options.delete(:recurse) ##patterns += patterns.collect{ |f| File.join(f, '**', '**') } multiglob_r(*patterns) end bitflags = 0 bitflags |= File::FNM_NOESCAPE if options[:noescape] bitflags |= File::FNM_CASEFOLD if options[:casefold] bitflags |= File::FNM_PATHNAME if options[:pathname] or options[:strict] bitflags |= File::FNM_DOTMATCH if options[:dotmatch] or options[:strict] patterns = [patterns].flatten.compact if options[:recurse] patterns += patterns.collect{ |f| File.join(f, '**', '**') } end files = [] files += patterns.collect{ |pattern| Dir.glob(pattern, bitflags) }.flatten.uniq return files end
The same as multiglob
, but recusively includes directories.
Dir.multiglob_r('tmp')
is equivalent to
Dir.multiglob('tmp', :recurse=>true)
The effect of which is
Dir.multiglob('tmp', 'tmp /**')
# File lib/facets/dir/multiglob.rb, line 66 def self.multiglob_r(*patterns) options = Hash === patterns.last ? patterns.pop : {} matches = multiglob(*patterns) directories = matches.select{ |m| File.directory?(m) } matches += directories.map{ |d| multiglob_r(File.join(d, '**'), options) }.flatten matches.uniq ##options = (Hash === patterns.last ? patterns.pop : {}) ##options[:recurse] = true ##patterns << options ##multiglob(*patterns) end
Is a path parental to another?
Dir.parent?('parent', 'parent/child') #=> true
TODO: Needs improvement.
TODO: Instance version?
# File lib/facets/dir/parent.rb, line 11 def self.parent?(parent_path, child_path) %r^#{Regexp.escape(parent_path)}| =~ child_path ? true : false end
Recursively scan a directory and pass each file to the given block.
Dir.recurse('.') do |path| # ... end
CREDIT: George Moschovitis
TODO: If fully compatible, reimplement as alias of Find.find, or just copy and paste Find.find code here if it looks more robust.
# File lib/facets/dir/recurse.rb, line 14 def self.recurse(path='.', &block) list = [] stoplist = ['.', '..'] Dir.foreach(path) do |f| next if stoplist.include?(f) filename = (path == '.' ? f : path + '/' + f) list << filename block.call(filename) if block if FileTest.directory?(filename) and not FileTest.symlink?(filename) list.concat(Dir.recurse(filename, &block)) end end list end
Public Instance Methods
Like each, except the “.” and “..” special files are ignored. You can use
ignore
to override '.' and '..' and ignore
other entries via a exact match or regular expression.
CREDIT: Tyler Rick
# File lib/facets/dir/each_child.rb, line 8 def each_child(*ignore) ignore = ['.', '..'] if ignore.empty? each do |file| yield file unless ignore.any?{ |i| i === file } end end