diff --git a/dir.rb b/dir.rb index 9436b48f474..461b344d180 100644 --- a/dir.rb +++ b/dir.rb @@ -213,200 +213,18 @@ class Dir end # call-seq: - # Dir[*patterns, base: nil, sort: true] -> array - # - # Calls Dir.glob with argument +patterns+ - # and the values of keyword arguments +base+ and +sort+; - # returns the array of selected entry names. + # Dir[patterns, base: nil, sort: true] -> array # + # Like Dir.glob, but does not accept keyword argument +flags+. def self.[](*args, base: nil, sort: true) Primitive.dir_s_aref(args, base, sort) end # call-seq: - # Dir.glob(patterns, flags: 0, base: nil, sort: true) -> array - # Dir.glob(patterns, flags: 0, base: nil, sort: true) {|entry_name| ... } -> nil - # - # Forms an array _entry_names_ of the entry names selected by the arguments. - # - # Argument +patterns+ is a string pattern or an array of string patterns; - # note that these are not regexps; see below. - # - # Notes for the following examples: - # - # - '*' is the pattern that matches any entry name - # except those that begin with '.'. - # - We use method Array#take to shorten returned arrays - # that otherwise would be very large. - # - # With no block, returns array _entry_names_; - # example (using the {simple file tree}[rdoc-ref:Dir@About+the+Examples]): - # - # Dir.glob('*') # => ["config.h", "lib", "main.rb"] - # - # With a block, calls the block with each of the _entry_names_ - # and returns +nil+: - # - # Dir.glob('*') {|entry_name| puts entry_name } # => nil - # - # Output: - # - # config.h - # lib - # main.rb - # - # If optional keyword argument +flags+ is given, - # the value modifies the matching; see below. - # - # If optional keyword argument +base+ is given, - # its value specifies the base directory. - # Each pattern string specifies entries relative to the base directory; - # the default is '.'. - # The base directory is not prepended to the entry names in the result: - # - # Dir.glob(pattern, base: 'lib').take(5) - # # => ["abbrev.gemspec", "abbrev.rb", "base64.gemspec", "base64.rb", "benchmark.gemspec"] - # Dir.glob(pattern, base: 'lib/irb').take(5) - # # => ["cmd", "color.rb", "color_printer.rb", "completion.rb", "context.rb"] - # - # If optional keyword +sort+ is given, its value specifies whether - # the array is to be sorted; the default is +true+. - # Passing value +false+ with that keyword disables sorting - # (though the underlying file system may already have sorted the array). - # - # Patterns - # - # Each pattern string is expanded - # according to certain metacharacters; - # examples below use the {Ruby file tree}[rdoc-ref:Dir@About+the+Examples]: - # - # - '*': Matches any substring in an entry name, - # similar in meaning to regexp /.*/mx; - # may be restricted by other values in the pattern strings: - # - # - '*' matches all entry names: - # - # Dir.glob('*').take(3) # => ["BSDL", "CONTRIBUTING.md", "COPYING"] - # - # - 'c*' matches entry names beginning with 'c': - # - # Dir.glob('c*').take(3) # => ["CONTRIBUTING.md", "COPYING", "COPYING.ja"] - # - # - '*c' matches entry names ending with 'c': - # - # Dir.glob('*c').take(3) # => ["addr2line.c", "array.c", "ast.c"] - # - # - '\*c\*' matches entry names that contain 'c', - # even at the beginning or end: - # - # Dir.glob('*c*').take(3) # => ["CONTRIBUTING.md", "COPYING", "COPYING.ja"] - # - # Does not match Unix-like hidden entry names ("dot files"). - # To include those in the matched entry names, - # use flag IO::FNM_DOTMATCH or something like '{*,.*}'. - # - # - '**': Matches entry names recursively - # if followed by the slash character '/': - # - # Dir.glob('**/').take(3) # => ["basictest/", "benchmark/", "benchmark/gc/"] - # - # If the string pattern contains other characters - # or is not followed by a slash character, - # it is equivalent to '*'. - # - # - '?' Matches any single character; - # similar in meaning to regexp /./: - # - # Dir.glob('io.?') # => ["io.c"] - # - # - '[set]': Matches any one character in the string _set_; - # behaves like a {Regexp character class}[rdoc-ref:Regexp@Character+Classes], - # including set negation ('[^a-z]'): - # - # Dir.glob('*.[a-z][a-z]').take(3) - # # => ["CONTRIBUTING.md", "COPYING.ja", "KNOWNBUGS.rb"] - # - # - '{abc,xyz}': - # Matches either string _abc_ or string _xyz_; - # behaves like {Regexp alternation}[rdoc-ref:Regexp@Alternation]: - # - # Dir.glob('{LEGAL,BSDL}') # => ["LEGAL", "BSDL"] - # - # More than two alternatives may be given. - # - # - \\: Escapes the following metacharacter. - # - # Note that on Windows, the backslash character may not be used - # in a string pattern: - # Dir['c:\\foo*'] will not work, use Dir['c:/foo*'] instead. - # - # More examples (using the {simple file tree}[rdoc-ref:Dir@About+the+Examples]): - # - # # We're in the example directory. - # File.basename(Dir.pwd) # => "example" - # Dir.glob('config.?') # => ["config.h"] - # Dir.glob('*.[a-z][a-z]') # => ["main.rb"] - # Dir.glob('*.[^r]*') # => ["config.h"] - # Dir.glob('*.{rb,h}') # => ["main.rb", "config.h"] - # Dir.glob('*') # => ["config.h", "lib", "main.rb"] - # Dir.glob('*', File::FNM_DOTMATCH) # => [".", "config.h", "lib", "main.rb"] - # Dir.glob(["*.rb", "*.h"]) # => ["main.rb", "config.h"] - # - # Dir.glob('**/*.rb') - # => ["lib/song/karaoke.rb", "lib/song.rb", "main.rb"] - # - # Dir.glob('**/*.rb', base: 'lib') # => ["song/karaoke.rb", "song.rb"] - # - # Dir.glob('**/lib') # => ["lib"] - # - # Dir.glob('**/lib/**/*.rb') # => ["lib/song/karaoke.rb", "lib/song.rb"] - # - # Dir.glob('**/lib/*.rb') # => ["lib/song.rb"] - # - # Flags - # - # If optional keyword argument +flags+ is given (the default is zero -- no flags), - # its value should be the bitwise OR of one or more of the constants - # defined in module File::Constants. - # - # Example: - # - # flags = File::FNM_EXTGLOB | File::FNM_DOTMATCH - # - # Specifying flags can extend, restrict, or otherwise modify the matching. - # - # The flags for this method (other constants in File::Constants do not apply): - # - # - File::FNM_DOTMATCH: - # specifies that entry names beginning with '.' - # should be considered for matching: - # - # Dir.glob('*').take(5) - # # => ["BSDL", "CONTRIBUTING.md", "COPYING", "COPYING.ja", "GPL"] - # Dir.glob('*', flags: File::FNM_DOTMATCH).take(5) - # # => [".", ".appveyor.yml", ".cirrus.yml", ".dir-locals.el", ".document"] - # - # - File::FNM_EXTGLOB: - # enables the pattern extension - # '{a,b}', which matches pattern _a_ and pattern _b_; - # behaves like a - # {regexp union}[rdoc-ref:Regexp.union] - # (e.g., '(?:a|b)'): - # - # pattern = '{LEGAL,BSDL}' - # Dir.glob(pattern) # => ["LEGAL", "BSDL"] - # - # - File::FNM_NOESCAPE: - # specifies that escaping with the backslash character '\' - # is disabled; the character is not an escape character. - # - # - File::FNM_PATHNAME: - # specifies that metacharacters '*' and '?' - # do not match directory separators. - # - # - File::FNM_SHORTNAME: - # specifies that patterns may match short names if they exist; Windows only. + # Dir.glob(patterns, flags: 0, base: '.', sort: true) -> array_of_entries # + # Returns an array of filesystem entries; + # see {Filename Globbing}[rdoc-ref:file/filename_globbing.md]. def self.glob(pattern, _flags = 0, flags: _flags, base: nil, sort: true) Primitive.attr! :use_block Primitive.dir_s_glob(pattern, flags, base, sort) diff --git a/doc/file/filename_globbing.md b/doc/file/filename_globbing.md index 9daad17fbd3..8c691cccda5 100644 --- a/doc/file/filename_globbing.md +++ b/doc/file/filename_globbing.md @@ -3,17 +3,58 @@ Filename globbing is a pattern-matching feature implemented in certain Ruby methods: - Dir.glob. -- [`Dir[]`](https://docs.ruby-lang.org/en/master/Dir.html#method-c-5B-5D). -- Pathname.glob. - Pathname#glob. +- [`Dir[]`](../Dir.html#method-c-5B-5D), + which is like Dir.glob except that it does not accept keyword argument `flags`. -Each `glob` method finds filesystem entries (files and directories) -that match certain patterns. +Each `glob` method selects filesystem entries (file and directory names) +that match certain patterns, +under the control of keyword arguments `base` and `flags`; +the selected entries may be sorted, according to keyword argument `sort`. -These methods are quite different +These filename-globbing methods are quite different from [filename-matching](rdoc-ref:filename_matching.md) methods, which match patterns against string paths, and do not access the filesystem. +Inputs to the filename-globbing methods: + +- The argument `patterns` is a string or an array of strings, + which are _not_ Regexp objects; + see [Patterns](#patterns). +- Keyword argument `base` specifies the entry in the filesystem where searching is to begin; + see [base](#base). +- Keyword argument `flags` specifies an integer value that may be defined by constants; + see [flags](#flags). + This argument is not available + in method [`Dir[]`](https://docs.ruby-lang.org/en/master/Dir.html#method-c-5B-5D), + for which the flags value is zero. +- Keyword argument `sort` specifies whether the returned array is to be sorted. + see [sort](#sort). + +Their return values: + +- Each of the methods `Dir[]` and Dir.glob returns an array of the selected string entries. +- \Method Pathname#glob with no block returns an array of Pathname objects + each based on a selected string entry. +- \Method Pathname#glob with a block calls the block with each pathname + based on a selected string entry. + +Examples: + +```ruby +Dir['*'].take(3) +# => ["BSDL", "CONTRIBUTING.md", "COPYING"] +Dir.glob('*').take(3) +# => ["BSDL", "CONTRIBUTING.md", "COPYING"] +Pathname('.').glob('*').take(3) +# => [#, #, #] +a = [] +Pathname('.').glob('*') {|pn| a << pn if pn.to_s.end_with?('.c') } # => nil +a.take(3) # => [#, #, #] +``` + +The examples below for Pathname#glob do not give blocks. + ## Patterns These are the basic elements of filename-globbing patterns; @@ -314,6 +355,8 @@ Pathname('lib/net').glob('*').take(3) # => [#, #, #] ``` +Note that the base directory is not prepended to the entry names in the result. + ### `flags` Optional keyword argument `flags` (defaults to `0`) may be the bitwise OR diff --git a/pathname_builtin.rb b/pathname_builtin.rb index 2cbb0f94c6e..00be5716717 100644 --- a/pathname_builtin.rb +++ b/pathname_builtin.rb @@ -1777,47 +1777,21 @@ class Pathname # * FileTest * end -class Pathname # * Dir * +class Pathname # call-seq: - # glob(patterns, **kwargs) → array_of_pathnames - # glob(patterns, **kwargs) {|pathname| ... } → nil + # glob(patterns, base: '.', flags: 0, sort: true) → array_of_pathnames + # glob(patterns, base: '.', flags: 0, sort: true) {|pathname| ... } → nil # - # Calls Dir.glob(patterns, **kwargs), which yields or returns entry names; - # see Dir.glob. + # Selects filesystem entries + # based on the given keyword arguments +base+, +flags+, and +sort+; + # see {Filename Globbing}[rdoc-ref:file/filename_globbing.md]. # - # Required argument +patterns+ is a string pattern or an array of string patterns; - # note that these patterns are not regexps. + # With no block given, returns an array of pathnames, + # each based on a selected filesystem entry. # - # Keyword arguments **kwargs are passed through to Dir.glob; - # see the documentation there. + # With a block given, calls the block with pathnames, + # each based on a selected filesytem entry. # - # With no block given, returns an array of \Pathname objects; - # each is Pathname.new(entry_name) for an entry name returned by Dir.glob. - # - # Pathname.glob('*').take(3) - # # => [#, #, #] - # Pathname.glob(['o*', 'a*']).take(3) - # # => [#, #, #] - # - # With a block given, calls the block with each pathname - # Pathname.new(entry_name), - # where each +entry_name+ is a \Pathname object created by the value yielded by Dir.glob. - # - # a = [] - # Pathname.glob(['o*', 'a*']) {|pathname| a << pathname } - # a.take(3) - # # => [#, #, #] - # - # Optional keyword argument +base+ is of particular interest. - # When it is given, its value specifies the base directory for the pathnames; - # each pattern string specifies entries relative to the base directory: - # - # Pathname.glob('*', base: 'lib').take(2) - # # => [#, #] - # Pathname.glob('*', base: 'lib/bundler').take(2) - # # => [#, #] - # - # Note that the base directory is not prepended to the entry names in the result. def Pathname.glob(*args, **kwargs) # :yield: pathname if block_given? Dir.glob(*args, **kwargs) {|f| yield self.new(f) }