通过Ruby stdlib从路径中提取规范化/规范目录名称?

时间:2014-11-15 17:52:55

标签: ruby

假设您有一个路径字符串,可以是以下之一:

  • 富/酒吧/ Baz.txt
  • 富/酒吧/
  • 富/酒吧

在每种情况下,您希望使用Ruby标准库中的方法隔离String中的目录层次结构,从而得到值Foo/Bar。有没有一种方法可以做到这一点?不幸的是,Path#cleanpath和API中的其他方法保留了字符串中的尾部斜杠。

是否有单一方法或简短方法链的行为如下?

File.directory?(path) ? path.chomp("/") : File.split(path)[0]

通过正则表达式获得所需行为的另一个例子是here in this question

2 个答案:

答案 0 :(得分:0)

不,似乎没有办法在Ruby API中明确地执行此操作。另一种方法是使用正则表达式similar to what you see here

答案 1 :(得分:0)

不太确定我是否理解您的问题,但是如果您想拆分目录和文件,可以这样:

path = "/etc/hosts" ; File.directory?(path) &&  [ File.dirname(path) + "/" +  
File.basename(path), nil ]  ||  [ File.dirname(path),  File.basename(path) ]
=> ["/etc", "hosts"]

path = "/var/lib" ; File.directory?(path) &&  [ File.dirname(path) + "/" +  
File.basename(path), nil ]  ||  [ File.dirname(path),  File.basename(path) ]
=> ["/var/lib", nil]

但是请注意,此解决方案仅适用于现有文件的域。如果您打算创建路径,则不可能知道答案中Bar的位置(在上面的示例中,它将被视为文件)。

请注意,答案应该是标准化的:

path = "//etc//hosts" ; File.directory?(path) &&  [ File.dirname(path) + "/" +  
File.basename(path), nil ]  ||  [ File.dirname(path),  File.basename(path) ]
=> ["/etc", "hosts"]

但是,dirname的规范化受到限制/难以解决(在我看来):

path = "/./etc//hosts" ; File.directory?(path) &&  [ File.dirname(path) + "/" 
+  File.basename(path), nil ]  ||  [ File.dirname(path),  File.basename(path) ]
=> ["/./etc", "hosts"]

解析很困难,只要有可能避免解析,您肯定会节省时间。与其标准化文件路径,不如相信它们的inode号(同样,仅对现有文件的域有效):

[ File.stat("/etc/hosts").ino , File.stat("/./etc/hosts").ino ]
=> [1309513, 1309513]