Project

General

Profile

Bug #16831

Running `Pathname#glob` with `File::FNM_DOTMATCH` option loses `.` and `..`

Added by jnchito (Junichi Ito) 9 months ago. Updated 8 months ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-darwin19]
[ruby-core:98144]

Description

Running Dir.glob, Pathname.glob with File::FNM_DOTMATCH option keeps . and .. as their basename:

require 'pathname'

pathname = Pathname.pwd
#=> #<Pathname:/Users/jnito/dev>

# Dir.glob keeps "." and ".."
Dir.glob(pathname.join('*'), File::FNM_DOTMATCH).sort[0..1]
#=> ["/Users/jnito/dev/.", "/Users/jnito/dev/.."]

# Pathname.glob keeps "." and ".." too
Pathname.glob(pathname.join('*'), File::FNM_DOTMATCH).sort[0..1]
#=> [#<Pathname:/Users/jnito/dev/.>, #<Pathname:/Users/jnito/dev/..>]

I expect Pathname#glob with File::FNM_DOTMATCH option has same behavior, but it loses . and ..:

# Pathname#glob loses "." and ".."
pathname.glob('*', File::FNM_DOTMATCH).sort[0..1]
#=> [#<Pathname:/Users/jnito>, #<Pathname:/Users/jnito/dev>]

I wanted to replace my code from Pathname.glob(pathname.join('*'), File::FNM_DOTMATCH) to pathname.glob('*', File::FNM_DOTMATCH), but I couldn't do due to their incompatibility. So I want Pathname#glob to keep . and ...


Related issues

Related to Ruby master - Bug #17280: Dir.glob with FNM_DOTMATCH matches ".." and "." and results in duplicated entriesClosedActions

Updated by nobu (Nobuyoshi Nakada) 9 months ago

Actually . and .. entries are kept.
Just Pathname("/Users/jnito/dev/..") is cleaned up as Pathname("/Users/jnito").

Updated by jnchito (Junichi Ito) 9 months ago

nobu (Nobuyoshi Nakada) wrote in #note-1:

Actually . and .. entries are kept.
Just Pathname("/Users/jnito/dev/..") is cleaned up as Pathname("/Users/jnito").

That's true, but I feel the following code should have consistent results:

require 'pathname'

pathname = Pathname.pwd

Pathname(Dir.glob(pathname.join('*'), File::FNM_DOTMATCH).sort[0]).basename.to_s
#=> .
Pathname.glob(pathname.join('*'), File::FNM_DOTMATCH).sort[0].basename.to_s
#=> .

# This line doesn't return "."
pathname.glob('*', File::FNM_DOTMATCH).sort[0].basename.to_s
#=> jnito

Updated by Dan0042 (Daniel DeLorme) 9 months ago

I don't think those can have consistent results, because Pathname#glob is equivalent to using the base option of Dir.glob and then joining the paths, which is not the same as joining the paths into a glob and then invoking Dir.glob. In particular they have different behavior if the base contains globbing characters. And I don't think there's a method of Pathname that allows to join without cleaning the path.

b = Pathname.new("ext")
b.glob("*").min            #=> #<Pathname:ext/-test->
Dir.glob("*", base: b).min #=> "-test-"
Dir.glob(b+"*").min        #=> "ext/-test-"

b = Pathname.new("{ext,man}")
b.glob("*").min            #=> nil because there's no literal "{ext,man}" dir
Dir.glob("*", base: b).min #=> nil
Dir.glob(b+"*").min        #=> "ext/-test-"

Updated by jnchito (Junichi Ito) 9 months ago

Thank you for your explanation. With your hint and reading the implementation code solved my question.

Dan0042 (Daniel DeLorme) wrote in #note-3:

I don't think those can have consistent results, because Pathname#glob is equivalent to using the base option of Dir.glob and then joining the paths, which is not the same as joining the paths into a glob and then invoking Dir.glob. In particular they have different behavior if the base contains globbing characters. And I don't think there's a method of Pathname that allows to join without cleaning the path.

b = Pathname.new("ext")
b.glob("*").min            #=> #<Pathname:ext/-test->
Dir.glob("*", base: b).min #=> "-test-"
Dir.glob(b+"*").min        #=> "ext/-test-"

b = Pathname.new("{ext,man}")
b.glob("*").min            #=> nil because there's no literal "{ext,man}" dir
Dir.glob("*", base: b).min #=> nil
Dir.glob(b+"*").min        #=> "ext/-test-"

Dan0042 (Daniel DeLorme) wrote in #note-3:

I don't think those can have consistent results, because Pathname#glob is equivalent to using the base option of Dir.glob and then joining the paths, which is not the same as joining the paths into a glob and then invoking Dir.glob. In particular they have different behavior if the base contains globbing characters. And I don't think there's a method of Pathname that allows to join without cleaning the path.

b = Pathname.new("ext")
b.glob("*").min            #=> #<Pathname:ext/-test->
Dir.glob("*", base: b).min #=> "-test-"
Dir.glob(b+"*").min        #=> "ext/-test-"

b = Pathname.new("{ext,man}")
b.glob("*").min            #=> nil because there's no literal "{ext,man}" dir
Dir.glob("*", base: b).min #=> nil
Dir.glob(b+"*").min        #=> "ext/-test-"
#5

Updated by jeremyevans0 (Jeremy Evans) 8 months ago

  • Status changed from Open to Closed
#6

Updated by Eregon (Benoit Daloze) 3 months ago

  • Related to Bug #17280: Dir.glob with FNM_DOTMATCH matches ".." and "." and results in duplicated entries added

Also available in: Atom PDF