接下来,如果字符串是 glob 模式,我想获取匹配数组,如果字符串只是普通路径,我想获取具有单个元素的数组 - 这个路径。
它们都是有效的全局模式。一个包含通配符,一个不包含。通过Pathname.glob() 运行它们,你总会得到一个数组。奖励,它会检查它是否匹配任何东西。
$ irb
2.3.3 :001 > require "pathname"
=> true
2.3.3 :002 > Pathname.glob("test.data")
=> [#<Pathname:test.data>]
2.3.3 :003 > Pathname.glob("test.*")
=> [#<Pathname:test.asm>, #<Pathname:test.c>, #<Pathname:test.cpp>, #<Pathname:test.csv>, #<Pathname:test.data>, #<Pathname:test.dSYM>, #<Pathname:test.html>, #<Pathname:test.out>, #<Pathname:test.php>, #<Pathname:test.pl>, #<Pathname:test.py>, #<Pathname:test.rb>, #<Pathname:test.s>, #<Pathname:test.sh>]
2.3.3 :004 > Pathname.glob("doesnotexist")
=> []
这是早期标准化和验证数据的好方法,因此程序的其余部分不必这样做。
如果您真的想弄清楚某个东西是文字路径还是 glob,您可以尝试扫描任何特殊的 glob 字符,但这很快就会变得复杂并且容易出错。它需要knowing how glob works in detail 并记得检查引用和转义。 foo* 具有全局模式。 foo\* 没有。 foo[123] 确实如此。 foo\[123] 没有。而且我不确定foo[123\] 在做什么,我认为它算作非终止集合。
一般来说,您希望避免编写必须重现另一段代码的内部工作的代码。如果有 Pathname.has_glob_chars 你可以使用它,但没有这样的东西。
Pathname.glob 使用 File.fnmatch 来进行 globbing,您可以在不接触文件系统的情况下使用它。你也许可以用它想出一些东西,但我不能让它工作。我想也许只有文字路径会匹配自己,但 foo* 打败了它。
相反,检查它是否存在。
Pathname.new(path).exist?
如果它存在,它就是一个真实文件的真实路径。如果它不存在,它可能是一条真实的路径,或者它可能是一个球体。这可能已经足够了。
您还可以通过查看 Pathname.glob(path) 是否返回与原始路径匹配的单个元素来进行检查。请注意,在匹配路径时,使用cleanpath 规范化双方非常重要。
paths = Pathname.glob(path)
if paths.size == 1 && paths[0].cleanpath == Pathname.new(path).cleanpath
puts "#{path} is a literal path"
elsif paths.size == 0
puts "#{path} matched nothing"
else
puts "#{path} was a glob"
end