我需要检查路径字符串a
表示的目录是否是路径字符串b
表示的目录或文件的祖先(或者是),并且两个路径实际存在
我天真的实现看起来像:
b.starts_with?(a) && File.exist?(b)
示例失败了:
# should be false
a = '/foo/bar'
b = '/foo/bartholomew/monkey'
# should be true
a = '/foo/bar'
b = '/foo/../foo/bar/monkey
我可以通过迭代文件b
的父项并检查是否有任何匹配a
来完成这项工作,但是公共库中是否有任何方法可以使它更简单,就像Python中的这个解决方案一样? - How can I tell if a file is a descendant of a given directory?
答案 0 :(得分:4)
不要对字符串进行操作,而是让目录列出并检查是否以另一个开头
def is_descendant?(a, b)
a_list = File.expand_path(a).split('/')
b_list = File.expand_path(b).split('/')
b_list[0..a_list.size-1] == a_list
end
is_descendant?('/foo/bar', '/foo/bartholomew/monkey') #=> false
is_descendant?('/foo/bar', '/foo/../foo/bar/monkey') #=> true
File.expand
似乎是Ruby相当于Python os.path.realpath
。
答案 1 :(得分:0)
这似乎适用于您的测试用例:
def descendant?(a, b)
[a, b].each { |x| x.replace File.expand_path(x) }
!b.split('/').zip(a.split('/')).any? { |x, y| y != nil && x != y }
end
descendant? '/foo/bar', '/foo/bartholomew/monkey' # => false
descendant? '/foo/bar', '/foo/../foo/bar/monkey' # => true
答案 2 :(得分:0)
我实现了这个,以便函数检查其中一个字符串是否是另一个字符串的祖先。在重新阅读你的问题时,这可能不是你想要的,但哦,好吧......
def path_components(path_string)
File.expand_path(path_string).split('/')
end
# Check if either x_str or y_str is an ancestor of the other.
def is_one_ancestor?(x_str, y_str)
x_parts = path_components(x_str)
y_parts = path_components(y_str)
shorter_length = [x_parts, y_parts].map(&:length).min
# Find the length of the common prefix of the two paths.
common_path_length = x_parts.zip(y_parts).take_while do |x,y|
x == y
end.length
# one is an ancestor of the other if the common path length
# is equal to the length of the shorter path
common_path_length == shorter_length
end
a = '/foo/bar'
b = '/foo/bartholomew/monkey'
puts is_one_ancestor?(a,b) # false
puts is_one_ancestor?(b,a) # false
c = '/foo/bar'
d = '/foo/../foo/bar/monkey'
puts is_one_ancestor?(c,d) # true
puts is_one_ancestor?(d,c) # true