Feature #6587
closedproposal: adding new methods File.rootname and Pathname#rootname
Description
=begin
みんな大好き Unixen ではパスの先頭は '/' で始まるものという暗黙の前提がありますが、Windows ではドライブレターおよび UNC というものがあるのでその前提が成り立たないことは広く知られていると思います。
Ruby はドライブレターや UNC はそれなりに適切に取り扱うようになっていますが、残念ながらパス名を処理する際には依然としてロジックを自前で用意する必要があります。
例えば ruby 配布物の test/ 以下を見ると、独自にドライブレター周りを扱おうとしているコードが散見されますが、それぞれ異なる処理を書いており、UNC や拡張パス名(という名前でいいかどうかわかりませんが、"//?/" あるいは "//./" で始まるもの)まで含めて適切に取り扱えているコードはほぼありません。
そこで、(({dirname}))、(({basename}))、(({extname})) などから類推して、(({rootname})) というメソッドを (({File})) の特異メソッドおよび (({Pathname})) のメソッドとして追加することを提案します。
--- File.rootname(filename) -> String
filename のうち、ルートディレクトリあるいはそれに相当する部分を文字列として返します。
filename が相対パスなどの場合は ""(空文字列)を返します。
# on Unixen
p File.rootname("/foo/bar.txt") #=> "/" (absolute path)
p File.rootname("bar.txt") #=> "" (relative path)
# on Windows
p File.rootname("/foo/bar.txt") #=> "" (relative path)
p File.rootname("bar.txt") #=> "" (relative path)
p File.rootname("C:/foo/bar.txt") #=> "C:/" (normal absolute path)
p File.rootname("C:bar.txt") #=> "" (relative path)
p File.rootname("//host/share/baz.txt") #=> "//host/share" (UNC absolute path)
p File.rootname("//?/C:/foo/bar.txt") #=> "//?/C:/" (extended form absolute path)
--- Pathname#rootname
Pathname.new(File.rootname(self.to_s)) と同じです。
=end
Files
Updated by kosaki (Motohiro KOSAKI) over 12 years ago
心情的には賛成なんですが。。
例えば ruby 配布物の test/ 以下を見ると、独自にドライブレター周りを扱おうとしているコードが散見されますが、
それぞれ異なる処理を書いており、UNC や拡張パス名(という名前でいいかどうかわかりませんが、"//?/" あるいは
"//./" で始まるもの)まで含めて適切に取り扱えているコードはほぼありません。
このパッチによってこのあたりがどこくらい綺麗に書けるようになるのかが、分かると積極的に賛成しやすいなあ、とか
思います。なにを心配してるかというと正規表現で書いた方が短くかけるなら、意識の高い人以外は誰も移行してくれなくて
賽の河原になるんじゃないかという不安がじゃっかんあったりなかったり
Updated by nobu (Nobuyoshi Nakada) over 12 years ago
- Description updated (diff)
=begin
: usa (Usaku NAKAMURA) wrote:
そこで、dirname、basename、extname などから類推して、rootname というメソッドを File の特異メソッドおよび Pathname のメソッドとして追加することを提案します。
--- File.rootname(filename) -> String
# on Windows
p File.rootname("/foo/bar.txt") #=> "" (relative path)
p File.rootname("C:bar.txt") #=> "" (relative path)
この2つの例だけ違和感があるのですが、それぞれ "/" と "C:" ではないかという気がしました。
具体的には、現在どういうコードが使われていて、それをどう置き換えることを想定しているのでしょうか。
=end
Updated by usa (Usaku NAKAMURA) over 12 years ago
こさきさんとなかださんにまとめて回答。
このパッチによってこのあたりがどこくらい綺麗に書けるようになるのかが、分かると積極的に賛成しやすいなあ、とか
具体的には、現在どういうコードが使われていて、それをどう置き換えることを想定しているのでしょうか。
そうですね、例えばtest/rake/test_rake_directory_task.rbの30~34行目に
drive = Dir.pwd
while drive != File.dirname(drive)
drive = File.dirname(drive)
end
drive = drive[0...-1] if drive[-1] == ?/
というコードがありますが、これは File.rootname(Dir.pwd) の一行で書けます。
また、test/fileutils/test_fileutils.rbの177~180行目に
root = have_drive_letter? ? 'C:/' : '/'
というコードがありますが、root = File.rootname(Dir.pwd) と書けさえすればCドライブが存在するという仮定が不要になります。
思います。なにを心配してるかというと正規表現で書いた方が短くかけるなら、意識の高い人以外は誰も移行してくれなくて 賽の河原になるんじゃないかという不安がじゃっかんあったりなかったり
少なくとも、私には正規表現であろうがなんだろうが短く正確に書ける自信はないです。
上のrakeのtestの例のようなものが最も確実ではないかと思っていますが、こう書くことを啓蒙して回る気はしないですね。します?
この2つの例だけ違和感があるのですが、それぞれ "/" と "C:" ではないかという気がしました。
rootじゃないものが取れてもしゃーないと思うので素直に諦めました。
あと、今見直して気付きましたが、
p File.rootname("//host/share/baz.txt") #=> "//host/share" (UNC absolute path)
は"//host/share/"になるべきでした。
Updated by kosaki (Motohiro KOSAKI) over 12 years ago
具体的には、現在どういうコードが使われていて、それをどう置き換えることを想定しているのでしょうか。
そうですね、例えばtest/rake/test_rake_directory_task.rbの30~34行目に
drive = Dir.pwd
while drive != File.dirname(drive)
drive = File.dirname(drive)
end
drive = drive[0...-1] if drive[-1] == ?/というコードがありますが、これは File.rootname(Dir.pwd) の一行で書けます。
また、test/fileutils/test_fileutils.rbの177~180行目にroot = have_drive_letter? ? 'C:/' : '/'
というコードがありますが、root = File.rootname(Dir.pwd) と書けさえすればCドライブが存在するという仮定が不要になります。
わたしは、これで説得されました。名前が rootname()がベストなのか自信がないので(他でroot nameという単語を見たことがないという
意味で)、ruby-coreで他にいい名前のアイデアないー?的なメールを出してくれるなら積極的賛成
Updated by nobu (Nobuyoshi Nakada) over 12 years ago
- File 0001-File.rootname.patch 0001-File.rootname.patch added
とりあえずパッチ置いときます。
Updated by nobu (Nobuyoshi Nakada) over 12 years ago
- Category set to core
- Assignee set to usa (Usaku NAKAMURA)
古いパッチを貼ってしまったので、最新版はこちらに置きました。
https://github.com/ruby/ruby/pull/130
Updated by usa (Usaku NAKAMURA) over 12 years ago
- Status changed from Open to Assigned
- Assignee changed from usa (Usaku NAKAMURA) to matz (Yukihiro Matsumoto)
なぜか私が担当になってましたが、それが通るなら勝手に入れるよ!
というわけでまつもとさんよろしくおねがいします。
Updated by matz (Yukihiro Matsumoto) over 12 years ago
WIndowsって /foo/bar,txt は絶対パスじゃないんですね。
となると、rootnameを作ってもUNIXとWindowsでの互換性の向上にはつながりませんよね。
例としてあげられたコードもWindows専用みたいだし。
では、UNIXでは変な値を返すよりもNotImplementedErrorの方がよかったりしません?
後は、名前は本当に適切なのかという点ですね。
個人的にはWindows専用にdriveなんとかって名前にしたほうが良いように思えますが。
Updated by kosaki (Motohiro KOSAKI) over 12 years ago
2012/7/13 matz (Yukihiro Matsumoto) matz@ruby-lang.org:
Issue #6587 has been updated by matz (Yukihiro Matsumoto).
WIndowsって /foo/bar,txt は絶対パスじゃないんですね。
カレントディレクトリが d:/hoge だと d:/foo/bar,txt に展開されてしまいますからね。
(いや、まともとさんも絶対知ってるはずだと思うんだけど・・・)
となると、rootnameを作ってもUNIXとWindowsでの互換性の向上にはつながりませんよね。
例としてあげられたコードもWindows専用みたいだし。
では、UNIXでは変な値を返すよりもNotImplementedErrorの方がよかったりしません?後は、名前は本当に適切なのかという点ですね。
個人的にはWindows専用にdriveなんとかって名前にしたほうが良いように思えますが。
Windows専用にしたほうがいいかどうかは門外漢なのでコメントしませんが、
UNC absolute path とかも統一的に扱えているのが元プロポーサルの利点だと思っているので
driveなんとかという名前は一般化がワンランク落ちてしまった印象を受けます
Updated by kosaki (Motohiro KOSAKI) over 12 years ago
WIndowsって /foo/bar,txt は絶対パスじゃないんですね。
カレントディレクトリが d:/hoge だと d:/foo/bar,txt に展開されてしまいますからね。
(いや、まともとさんも絶対知ってるはずだと思うんだけど・・・)
うーん、うそを言った気がする。
http://msdn.microsoft.com/ja-jp/library/system.io.path.getpathroot(v=vs.71)
あたりを見るとMicrosoftの用語ではこれは「現在のドライブに対する絶対パス」というらしい。(なんじゃそりゃ)
たぶん、rootが複数あるんだから絶対パスはパスのユニーク性を保証しなくてあたりまえという哲学なんでしょう。推測ですが。で、なんとなく用語をwin
portではMSと合わせたほうがいいような気がしてちょっとぐぐってたんですが
http://hp.vector.co.jp/authors/VA022575/c/path.html
とかを見るとMSの用語もデタラメとか書いてあって悩みは増すばかり・・・・
Updated by usa (Usaku NAKAMURA) over 12 years ago
こんにちは、なかむら(う)です。
In message "[ruby-dev:45944] [ruby-trunk - Feature #6587] proposal: adding new methods File.rootname and Pathname#rootname"
on Jul.14,2012 00:16:18, matz@ruby-lang.org wrote:
となると、rootnameを作ってもUNIXとWindowsでの互換性の向上にはつながりませんよね。
例としてあげられたコードもWindows専用みたいだし。
では、UNIXでは変な値を返すよりもNotImplementedErrorの方がよかったりしません?
"/" が変な値かどうかよくわかりませんが(変なの?)、確かに互換性
の向上に繋がるようなユースケースは思いつきませんねえ。
UNIX側にあって困ることがあるのかどうかはよくわかりません。
後は、名前は本当に適切なのかという点ですね。
個人的にはWindows専用にdriveなんとかって名前にしたほうが良いように思えますが。
これは小崎さんが言っておられるようにドライブのみを扱うわけじ
ゃないのでdriveなんとかはあまりよくないと思っています。
UNIXで絶対に不要なら、windows_rootnameとかにしますか?
それでは。¶
U.Nakamura usa@garbagecollect.jp
Updated by matz (Yukihiro Matsumoto) over 12 years ago
- Status changed from Assigned to Rejected
Updated by Anonymous over 12 years ago
まつもと ゆきひろです
In message "Re: [ruby-dev:45967] Re: [ruby-trunk - Feature #6587] proposal: adding new methods File.rootname and Pathname#rootname"
on Tue, 17 Jul 2012 10:37:18 +0900, "U.Nakamura" usa@garbagecollect.jp writes:
|> 例としてあげられたコードもWindows専用みたいだし。
|> では、UNIXでは変な値を返すよりもNotImplementedErrorの方がよかったりしません?
|
|"/" が変な値かどうかよくわかりませんが(変なの?)、確かに互換性
|の向上に繋がるようなユースケースは思いつきませんねえ。
|UNIX側にあって困ることがあるのかどうかはよくわかりません。
困ることはないでしょうけど、意味不明ですよね。
|これは小崎さんが言っておられるようにドライブのみを扱うわけじ
|ゃないのでdriveなんとかはあまりよくないと思っています。
|UNIXで絶対に不要なら、windows_rootnameとかにしますか?
UNCなんちゃらを扱うUNIXでも意味のある拡張というのはありえる
のかもしれません。知らんけど。
いずれにしても現在の提案は、名前・挙動ともに完全には賛成でき
ないので、一度リジェクトします。もうしちゃったけど。
Windows専用にするか、汎用のユースケースをあげるか、どちらでも
いいけど、必要なら再提案してください。
まつもと ゆきひろ /:|)