确定Ruby中的一条路径是否在另一条路径下?

时间:2014-01-21 15:48:01

标签: ruby

我有两条路径:应用程序根路径和目标路径。确保目标路径是应用程序根路径的子节点的最简单方法是什么?

基本上,用户提供的目标路径将由我的服务器显示。但我想约束我的服务器,因此只有应用程序根路径下的文件可以显示。所以我想检查目标路径是否在根路径下。

根路径可以包含嵌套目录。

6 个答案:

答案 0 :(得分:3)

另一种方式:

def child?(root, target)
  raise ArgumentError, "target.size=#{target.size} < #{root.size} = root.size"\
    if target.size < root.size

  target[0...root.size] == root &&
    (target.size == root.size || target[root.size] == ?/)
end

root = "/root/app"

p child?(root, "/root/app/some/path") # => true
p child?(root, "/root/apple")         # => false 
p child?(root, "/root/app")           # => true
p child?(root, "/root")               # => ArgumentError: target.size = 5 < 9 = root.size

答案 1 :(得分:2)

也许效率低下但是万无一失

require 'find'
Find.find(root).include?(target)

答案 2 :(得分:1)

正则表达式怎么样:

root = "/root/app/"
target = "/root/app/some/path"

target =~ /^#{root}/

如果需要,您可以使用Pathname#realdirpath将相对路径转换为绝对路径。

答案 3 :(得分:1)

您尚未提供任何用例,因此我假设以下变量适用于您的案例

root =   "/var/www/"
target = "/var/www/logs/something/else.log"

您可以使用正则表达式或更简单的String#start_with?

target.start_with?(root)

答案 4 :(得分:0)

要避免路径注入,可以使用File.path方法:

[21] pry(main)> path_1 = File.path(Rails.root.join('public', '../config/routes.rb') )
=> "/project_path/config/routes.rb"
[22] pry(main)> path_2 = File.path(Rails.root.join('public', 'robots.txt') )
=> "/project_path/public/robots.txt"
[24] pry(main)> path_1.include?(Rails.root.join('public').to_s )
=> false
[25] pry(main)> path_2.include?(Rails.root.join('public').to_s )
=> true

答案 5 :(得分:0)

我喜欢Pathname#ascend

ancestor = Pathnew.new(path1).realdirpath
descendant = Pathnew.new(path2).realdirpath
descendant.ascend { |path| break true if path == ancestor } || false

Pathname#== 通过字符串比较工作,因此它有助于先使用 #realdirpath 清理您的输入。)