> Sure, I can write a clumsy loop like the following:
> def File.head_tail_split(fname) > s = fname > t = [] > h = nil > until s == '.' > t << h > s, h = *split(s) > end > return h, File.join(*t.compact) > end
> But I'm betting there's a better way. Or maybe there's already an easy > way I'm overlooking?
Check out the Pathname feature:
require 'pathname'
p = Pathname.new("a/b/c")
You get p.basename and p.dirname. Both return Pathname objects, but they're quite string-like and easily converted.
David
-- Rails training from David A. Black and Ruby Power and Light: Intro to Ruby on Rails July 21-24 Edison, NJ * Advancing With Rails August 18-21 Edison, NJ * Co-taught by D.A. Black and Erik Kastner See http://www.rubypal.com for details and updates!
path.scan(/([^\/]+)\/(.*)/) # with the String path
Pathname#cleanpath might come in handy if you're rolling your own. So might File::Separator.
David
-- Rails training from David A. Black and Ruby Power and Light: Intro to Ruby on Rails July 21-24 Edison, NJ * Advancing With Rails August 18-21 Edison, NJ * Co-taught by D.A. Black and Erik Kastner See http://www.rubypal.com for details and updates!
That's basically were I ended up too, but using David's File::Separator suggestion.
However you made me think it would be helpful for Pathname to have:
class Pathname def to_a to_s.split(File::Separator) # better definition ? end end
The funny thing is that reminds me of a rewrite of Pathname I did a while back that used an internal array instead of a string to store the path. It was ~20% faster than the current lib. But alas, no one cared :(
> Sure, I can write a clumsy loop like the following:
> def File.head_tail_split(fname) > s = fname > t = [] > h = nil > until s == '.' > t << h > s, h = *split(s) > end > return h, File.join(*t.compact) > end
> But I'm betting there's a better way. Or maybe there's already an easy > way I'm overlooking
cfp:~ > cat a.rb path = File.join 'a', 'b', 'c'
head, tail = path.split( File::SEPARATOR, 2 )
p :head => head, :tail => tail
cfp:~ > ruby a.rb {:tail=>"b/c", :head=>"a"}
a @ http://codeforpeople.com/ -- we can deny everything, except that we have the possibility of being better. simply reflect on that. h.h. the 14th dalai lama
Bill Walton wrote: >> That would be safer if fname were a Pathname.
> Not sure what you mean here by 'safer'. Say more?
At work we just finished a rewrite of a system that generously manipulated folders, paths, and files. The old system originally used only strings, and string surgery, to manipulate paths. (The old system was also very shabby and patched up; it started as a one-shot script with no structure, etc.)
In the new system we follow a simple rule: If it's a filename, relative path, or absolute path of any kind, it's a Pathname. This allows us to stay within the Pathname feature set, and manipulate paths without any string surgery. The result is much more typesafe.
In theory, Pathnames would be safer if you needed to support \ path delimiters, and if you needed to support paths with embedded \ or / characters. We are very good string surgeons, so we never had those problems.
>> Sure, I can write a clumsy loop like the following:
>> def File.head_tail_split(fname) >> s = fname >> t = [] >> h = nil >> until s == '.' >> t << h >> s, h = *split(s) >> end >> return h, File.join(*t.compact) >> end
>> But I'm betting there's a better way. Or maybe there's already an easy >> way I'm overlooking
Ironically, I tried that first and discarded it because I had misunderstood Tom's question and thought he wanted dirname/basename, and then didn't resurrect it when I finally understood :-) The only tweak I might make would be to use Pathname#clean (or roll one's own) in case there are consecutive separators.
David
-- Rails training from David A. Black and Ruby Power and Light: * Advancing With Rails August 18-21 Edison, NJ * Co-taught by D.A. Black and Erik Kastner See http://www.rubypal.com for details and updates!