疑問に思った点
Dir.globやPathname.globでワイルドカード(*)を指定し、なおかつFile::FNM_DOTMATCHオプションを渡すと、.や..が含まれるパスが返ってきます。
require 'pathname'
pathname = Pathname.pwd
# => #<Pathname:/Users/jnito/dev>
# Dir.glob は "." と ".." を保持する
Dir.glob(pathname.join('*'), File::FNM_DOTMATCH).sort[0..1]
# => ["/Users/jnito/dev/.", "/Users/jnito/dev/.."]
# Pathname.glob も "." と ".." を保持する
Pathname.glob(pathname.join('*'), File::FNM_DOTMATCH).sort[0..1]
# => [#<Pathname:/Users/jnito/dev/.>, #<Pathname:/Users/jnito/dev/..>]
しかし、Pathname#glob(インスタンスメソッドのglob)を使うと.や..が消えて、カレントディレクトリや親ディレクトリそのものが返ってきます。
require 'pathname'
pathname = Pathname.pwd
# => #<Pathname:/Users/jnito/dev>
# Dir.globやPathname.globと異なり、インスタンスメソッドのglobは"."や".."ではなく、カレントディレクトリや親ディレクトリが返ってくる
pathname.glob('*', File::FNM_DOTMATCH).sort[0..1]
# => [#<Pathname:/Users/jnito>, #<Pathname:/Users/jnito/dev>]
僕としてはクラスメソッドのPathname.globを呼びだしたときと同じように#<Pathname:/Users/jnito/dev/.>や#<Pathname:/Users/jnito/dev/..>が返ってきてほしかったのですが、この挙動の違いはどういう理由で発生するのでしょうか?その理由を以下にまとめます。
結果が異なる理由
Pathname.globはDir.globの結果をそのままPathnameオブジェクトに変換します。イメージとしては以下のような感じです。(実際はCで実装されています)
class Pathname
# クラスメソッドのglobの実装イメージ
def self.glob(pattern, flags=0)
Dir.glob(pattern, flags).map do |path|
Pathname(path)
end
end
end
一方、インスタンスメソッドのPathname#globはDir.globのbaseオプションに自分自身のパスを設定し、Dir.globの結果と自分自身を表すパスを+で結合します。イメージとしては以下のような感じです。(こちらも実際はCで実装されています)
class Pathname
# インスタンスメソッドのglobの実装イメージ
def glob(pattern, flags=0)
Dir.glob(pattern, flags, base: self).map do |path|
self + path
end
end
end
ポイントとなるのはself + pathの部分です。
baseオプションを指定すると、Dir.globは.や..という文字列を返します(=baseからの相対パスを返す)。そしてこれらの文字列をPathnameオブジェクトに+で結合すると、.や..が消えて、カレントディレクトリや親ディレクトリのパスが返ります。
pathname = Pathname.pwd
# => #<Pathname:/Users/jnito/dev>
# "."を結合すると、"."が消えてカレントディレクトリのパスになる
pathname + '.'
# => #<Pathname:/Users/jnito/dev>
# ".."を結合すると、".."が消えて親ディレクトリのパスになる
pathname + '..'
# => #<Pathname:/Users/jnito>
# "."や".."でなければ、素直にパスが結合される
pathname + 'foo'
# => #<Pathname:/Users/jnito/dev/foo>
インスタンスメソッドのPathname#globは内部的に以下のような処理が行われているため、File::FNM_DOTMATCHオプションを渡しても.や..が保持されず、カレントディレクトリや親ディレクトリが返ってくる、というわけです。