检查给定文件/目录是否在某个其他目录(或其子目录之一)中最好的方法是什么?平台独立性和绝对/相对路径处理会很好。
一种简单的方法就是搜索文件并每次检查,但也许有更好的文件。
e.g。给定目录A
,A
位于以B
为根的目录子树中的任何位置,即is_underneath?(A,B)
或其他内容。
答案 0 :(得分:4)
一个好的,快速的方法是在Ruby stdlib中使用Dir
类提供的glob
方法。
glob( pattern, [flags] ) # => matches
扩展模式,它是一个模式数组或模式字符串,并将结果作为匹配或作为赋予块的参数返回。
适用于文件和目录,并允许您递归搜索。 它返回一个数组,其中的文件/目录与模式匹配,如果没有人匹配,它将为空。
root = '/my_root'
value = 'et_voila.txt'
Dir.glob("#{root}/**/#{value}")
# ** Matches directories recursively.
# or you can pass also the relative path
Dir.glob("./foo/**/#{value}")
答案 1 :(得分:2)
我希望我理解你的问题是正确的。
一个例子:
require 'pathname'
A = '/usr/xxx/a/b/c.txt'
path = Pathname.new(A)
[
'/usr/xxx/a/b',
'/usr/yyy/a/b',
].each{|b|
if path.fnmatch?(File.join(b,'**'))
puts "%s is in %s" % [A,b]
else
puts "%s is not in %s" % [A,b]
end
}
结果:
/usr/xxx/a/b/c.txt is in /usr/xxx/a/b
/usr/xxx/a/b/c.txt is not in /usr/yyy/a/b
解决方案使用class Pathname。它的一个优点:Pathname表示文件系统上的文件或目录的名称,但不代表文件本身。因此,您可以在没有文件读取权限的情况下进行测试。
测试本身使用Pathname#fnmatch?
和glob-pattern File.join(path,'**')
(**
表示所有子目录)。
如果您经常需要,可以延长Pathname
:
require 'pathname'
class Pathname
def is_underneath?(path)
return self.fnmatch?(File.join(path,'**'))
end
end
A = '/usr/xxx/a/b/c.txt'
path = Pathname.new(A)
[
'/usr/xxx/a/b',
'/usr/yyy/a/b',
].each{|b|
if path.is_underneath?(b)
puts "%s is in %s" % [A,b]
else
puts "%s is not in %s" % [A,b]
end
}
要处理绝对/相对路径,可能有助于扩展这些路径(抱歉,这是未经测试的)。
class Pathname
def is_underneath?(path)
return self.expand_path.fnmatch?(File.expand_path(File.join(path,'**')))
end
end