Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DOC] File.fnmatch #4514

Merged
merged 2 commits into from
May 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 1 addition & 94 deletions dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -3180,100 +3180,7 @@ fnmatch_brace(const char *pattern, VALUE val, void *enc)
return (fnmatch(pattern, enc, RSTRING_PTR(path), arg->flags) == 0);
}

/*
* call-seq:
* File.fnmatch( pattern, path, [flags] ) -> (true or false)
* File.fnmatch?( pattern, path, [flags] ) -> (true or false)
*
* Returns true if +path+ matches against +pattern+. The pattern is not a
* regular expression; instead it follows rules similar to shell filename
* globbing. It may contain the following metacharacters:
*
* <code>*</code>::
* Matches any file. Can be restricted by other values in the glob.
* Equivalent to <code>/ .* /x</code> in regexp.
*
* <code>*</code>:: Matches all files regular files
* <code>c*</code>:: Matches all files beginning with <code>c</code>
* <code>*c</code>:: Matches all files ending with <code>c</code>
* <code>\*c*</code>:: Matches all files that have <code>c</code> in them
* (including at the beginning or end).
*
* To match hidden files (that start with a <code>.</code> set the
* File::FNM_DOTMATCH flag.
*
* <code>**</code>::
* Matches directories recursively or files expansively.
*
* <code>?</code>::
* Matches any one character. Equivalent to <code>/.{1}/</code> in regexp.
*
* <code>[set]</code>::
* Matches any one character in +set+. Behaves exactly like character sets
* in Regexp, including set negation (<code>[^a-z]</code>).
*
* <code> \ </code>::
* Escapes the next metacharacter.
*
* <code>{a,b}</code>::
* Matches pattern a and pattern b if File::FNM_EXTGLOB flag is enabled.
* Behaves like a Regexp union (<code>(?:a|b)</code>).
*
* +flags+ is a bitwise OR of the <code>FNM_XXX</code> constants. The same
* glob pattern and flags are used by Dir::glob.
*
* Examples:
*
* File.fnmatch('cat', 'cat') #=> true # match entire string
* File.fnmatch('cat', 'category') #=> false # only match partial string
*
* File.fnmatch('c{at,ub}s', 'cats') #=> false # { } isn't supported by default
* File.fnmatch('c{at,ub}s', 'cats', File::FNM_EXTGLOB) #=> true # { } is supported on FNM_EXTGLOB
*
* File.fnmatch('c?t', 'cat') #=> true # '?' match only 1 character
* File.fnmatch('c??t', 'cat') #=> false # ditto
* File.fnmatch('c*', 'cats') #=> true # '*' match 0 or more characters
* File.fnmatch('c*t', 'c/a/b/t') #=> true # ditto
* File.fnmatch('ca[a-z]', 'cat') #=> true # inclusive bracket expression
* File.fnmatch('ca[^t]', 'cat') #=> false # exclusive bracket expression ('^' or '!')
*
* File.fnmatch('cat', 'CAT') #=> false # case sensitive
* File.fnmatch('cat', 'CAT', File::FNM_CASEFOLD) #=> true # case insensitive
* File.fnmatch('cat', 'CAT', File::FNM_SYSCASE) #=> true or false # depends on the system default
*
* File.fnmatch('?', '/', File::FNM_PATHNAME) #=> false # wildcard doesn't match '/' on FNM_PATHNAME
* File.fnmatch('*', '/', File::FNM_PATHNAME) #=> false # ditto
* File.fnmatch('[/]', '/', File::FNM_PATHNAME) #=> false # ditto
*
* File.fnmatch('\?', '?') #=> true # escaped wildcard becomes ordinary
* File.fnmatch('\a', 'a') #=> true # escaped ordinary remains ordinary
* File.fnmatch('\a', '\a', File::FNM_NOESCAPE) #=> true # FNM_NOESCAPE makes '\' ordinary
* File.fnmatch('[\?]', '?') #=> true # can escape inside bracket expression
*
* File.fnmatch('*', '.profile') #=> false # wildcard doesn't match leading
* File.fnmatch('*', '.profile', File::FNM_DOTMATCH) #=> true # period by default.
* File.fnmatch('.*', '.profile') #=> true
*
* rbfiles = '**' '/' '*.rb' # you don't have to do like this. just write in single string.
* File.fnmatch(rbfiles, 'main.rb') #=> false
* File.fnmatch(rbfiles, './main.rb') #=> false
* File.fnmatch(rbfiles, 'lib/song.rb') #=> true
* File.fnmatch('**.rb', 'main.rb') #=> true
* File.fnmatch('**.rb', './main.rb') #=> false
* File.fnmatch('**.rb', 'lib/song.rb') #=> true
* File.fnmatch('*', 'dave/.profile') #=> true
*
* pattern = '*' '/' '*'
* File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME) #=> false
* File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
*
* pattern = '**' '/' 'foo'
* File.fnmatch(pattern, 'a/b/c/foo', File::FNM_PATHNAME) #=> true
* File.fnmatch(pattern, '/a/b/c/foo', File::FNM_PATHNAME) #=> true
* File.fnmatch(pattern, 'c:/a/b/c/foo', File::FNM_PATHNAME) #=> true
* File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME) #=> false
* File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
*/
/* :nodoc: */
static VALUE
file_s_fnmatch(int argc, VALUE *argv, VALUE obj)
{
Expand Down
98 changes: 98 additions & 0 deletions dir.rb
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,101 @@ def self.glob(pattern, _flags = 0, flags: _flags, base: nil, sort: true)
Primitive.dir_s_glob(pattern, flags, base, sort)
end
end

class << File
# call-seq:
# File.fnmatch( pattern, path, [flags] ) -> (true or false)
# File.fnmatch?( pattern, path, [flags] ) -> (true or false)
#
# Returns true if +path+ matches against +pattern+. The pattern is not a
# regular expression; instead it follows rules similar to shell filename
# globbing. It may contain the following metacharacters:
#
# <code>*</code>::
# Matches any file. Can be restricted by other values in the glob.
# Equivalent to <code>/ .* /x</code> in regexp.
#
# <code>*</code>:: Matches all files regular files
# <code>c*</code>:: Matches all files beginning with <code>c</code>
# <code>*c</code>:: Matches all files ending with <code>c</code>
# <code>\*c*</code>:: Matches all files that have <code>c</code> in them
# (including at the beginning or end).
#
# To match hidden files (that start with a <code>.</code> set the
# File::FNM_DOTMATCH flag.
#
# <code>**</code>::
# Matches directories recursively or files expansively.
#
# <code>?</code>::
# Matches any one character. Equivalent to <code>/.{1}/</code> in regexp.
#
# <code>[set]</code>::
# Matches any one character in +set+. Behaves exactly like character sets
# in Regexp, including set negation (<code>[^a-z]</code>).
#
# <code> \ </code>::
# Escapes the next metacharacter.
#
# <code>{a,b}</code>::
# Matches pattern a and pattern b if File::FNM_EXTGLOB flag is enabled.
# Behaves like a Regexp union (<code>(?:a|b)</code>).
#
# +flags+ is a bitwise OR of the <code>FNM_XXX</code> constants. The same
# glob pattern and flags are used by Dir::glob.
#
# Examples:
#
# File.fnmatch('cat', 'cat') #=> true # match entire string
# File.fnmatch('cat', 'category') #=> false # only match partial string
#
# File.fnmatch('c{at,ub}s', 'cats') #=> false # { } isn't supported by default
# File.fnmatch('c{at,ub}s', 'cats', File::FNM_EXTGLOB) #=> true # { } is supported on FNM_EXTGLOB
#
# File.fnmatch('c?t', 'cat') #=> true # '?' match only 1 character
# File.fnmatch('c??t', 'cat') #=> false # ditto
# File.fnmatch('c*', 'cats') #=> true # '*' match 0 or more characters
# File.fnmatch('c*t', 'c/a/b/t') #=> true # ditto
# File.fnmatch('ca[a-z]', 'cat') #=> true # inclusive bracket expression
# File.fnmatch('ca[^t]', 'cat') #=> false # exclusive bracket expression ('^' or '!')
#
# File.fnmatch('cat', 'CAT') #=> false # case sensitive
# File.fnmatch('cat', 'CAT', File::FNM_CASEFOLD) #=> true # case insensitive
# File.fnmatch('cat', 'CAT', File::FNM_SYSCASE) #=> true or false # depends on the system default
#
# File.fnmatch('?', '/', File::FNM_PATHNAME) #=> false # wildcard doesn't match '/' on FNM_PATHNAME
# File.fnmatch('*', '/', File::FNM_PATHNAME) #=> false # ditto
# File.fnmatch('[/]', '/', File::FNM_PATHNAME) #=> false # ditto
#
# File.fnmatch('\?', '?') #=> true # escaped wildcard becomes ordinary
# File.fnmatch('\a', 'a') #=> true # escaped ordinary remains ordinary
# File.fnmatch('\a', '\a', File::FNM_NOESCAPE) #=> true # FNM_NOESCAPE makes '\' ordinary
# File.fnmatch('[\?]', '?') #=> true # can escape inside bracket expression
#
# File.fnmatch('*', '.profile') #=> false # wildcard doesn't match leading
# File.fnmatch('*', '.profile', File::FNM_DOTMATCH) #=> true # period by default.
# File.fnmatch('.*', '.profile') #=> true
#
# rbfiles = '**/*.rb'
# File.fnmatch(rbfiles, 'main.rb') #=> false
# File.fnmatch(rbfiles, './main.rb') #=> false
# File.fnmatch(rbfiles, 'lib/song.rb') #=> true
# File.fnmatch('**.rb', 'main.rb') #=> true
# File.fnmatch('**.rb', './main.rb') #=> false
# File.fnmatch('**.rb', 'lib/song.rb') #=> true
# File.fnmatch('*', 'dave/.profile') #=> true
#
# pattern = '*/*'
# File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME) #=> false
# File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
#
# pattern = '**/foo'
# File.fnmatch(pattern, 'a/b/c/foo', File::FNM_PATHNAME) #=> true
# File.fnmatch(pattern, '/a/b/c/foo', File::FNM_PATHNAME) #=> true
# File.fnmatch(pattern, 'c:/a/b/c/foo', File::FNM_PATHNAME) #=> true
# File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME) #=> false
# File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
def fnmatch(pattern, path, flags = nil)
end
alias fnmatch? fnmatch
end if false