diff options
Diffstat (limited to 'doc/file')
| -rw-r--r-- | doc/file/filename_globbing.md | 301 | ||||
| -rw-r--r-- | doc/file/filename_matching.md | 356 | ||||
| -rw-r--r-- | doc/file/timestamps.md | 83 |
3 files changed, 740 insertions, 0 deletions
diff --git a/doc/file/filename_globbing.md b/doc/file/filename_globbing.md new file mode 100644 index 0000000000..7981964c5c --- /dev/null +++ b/doc/file/filename_globbing.md @@ -0,0 +1,301 @@ +# Filename Globbing + +Filename globbing is a pattern-matching feature implemented in certain Ruby methods. + +Filename-globbing methods find filesystem entries (files and directories) +that match certain patterns; +these methods are: + +- Dir.glob. +- [`Dir[]`](https://docs.ruby-lang.org/en/master/Dir.html#method-c-5B-5D). +- Pathname.glob. +- Pathname#glob. + +These methods are quite different from filename-matching methods (not discussed here), +which match patterns against string paths, and do not access the filesystem; +those methods are: + +- File.fnmatch. +- Pathname#fnmatch. + +These are the basic elements of filename-globbing patterns; +see the sections below for details: + +| Pattern | Meaning | Examples | +|:------------------------:|------------------------------------------|------------------------------| +| Simple string. | Matches itself. | `'LEGAL'` | +| `'*'` | Matches any sequence of characters. | `'*.txt'` | +| `'?'` | Matches any single character. | `'?.txt'` | +| `'[abc]'`,<br>`'[^abc]'` | Matches a single character from a set. | `'x[abc]y'`,<br>`'x[^abc]y'` | +| `'[a-z]`',<br>`'[^a-z]'` | Matches a single character from a range. | `'x[0-9]y'`,<br>`'x[^0-9]y'` | +| `'{ , }'` | Matches alternatives. | `'{abc,def}'` | +| `'**'` | Matches directories recursively. | `'**/test.rb'` | +| `'\'` | Escapes the next character. | `'\\*'`, `'\?'` | + +## Patterns + +### Simple \String + +A "simple string" is one that does not contain special filename-globbing patterns; +see the table above. + +A simple string matches itself: + +```ruby +Dir.glob('LEGAL') # => ["LEGAL"] +Dir.glob('LEGA') # => [] # Must be exact. +Dir.glob('legal') # => [] # Case-sensitive. +``` + +Note that case-sensitivity may _not_ be modified by flags. + +By default, the Windows short name pattern is disabled: + +```ruby +Dir.glob('PROGRAM~1') # => [] +``` + +It may be enabled by flag [`File::FNM_SHORTNAME`](#constant-filefnmshortname). + + +### Any Sequence of Characters (`'*'`) + +The asterisk pattern (`'*'`) matches any sequence of characters: + +```ruby +Dir.glob('*').take(3) # => ["BSDL", "CONTRIBUTING.md", "COPYING"] +Dir.glob('\*') # => [] # Escaped. +``` + +By default, the asterisk pattern does not match a leading period (as in a dot-file): + +```ruby +Dir.glob('*').select {|entry| entry.start_with?('.') } # => [] +``` + +That matching may be enabled by flag [`File::FNM_DOTMATCH`](#constant-filefnmdotmatch). + +The asterisk pattern does not match across file separators: + +```ruby +Dir.glob('*.rb').select {|entry| entry.include?('/') } # => [] +``` + +Therefore flag File::FNM_PATHNAME does not affect the pattern. + +### Single Character (`'?'`) + +The question-mark pattern (`'?'`) matches any single character: + +```ruby +Dir.glob('???') # => ["GPL", "bin", "doc", "enc", "ext", "jit", "lib", "man"] +Dir.glob('??') # => ["gc"] # Only one entry with a 2-character name. +Dir.glob('?') # => [] # No entries with a 1-character name. +Dir.glob('\?') # => [] # No entries containing character '?'. +``` + +By default, the question-mark pattern does not match a leading period (as in a dot-file): + +```ruby +Dir.glob(".???") # => [".git"] +Dir.glob("????").select {|entry| entry.start_with?('.') } # => [] +``` + +That matching may be enabled by flag [`File::FNM_DOTMATCH`](#constant-filefnmdotmatch). + +### Single Character from a Set (`'[abc]'`, `'[^abc]'`) + +Characters enclosed in square brackets define a set of characters, +any of which matches a single character: + +```ruby +Dir.glob('[efgh][abcd]') # => ["gc"] +Dir.glob('\[efgh][abcd]') # => [] # Escaped. +``` + +The character set may be negated: + +```ruby +Dir.glob('[^abcd][^efgh]') # => ["gc"] +``` + +### Single Character from a \Range (`'[a-c]'`, `'[^a-c]'`) + +A range of characters enclosed in square brackets defines a set of characters, +any of which matches a single character: + +```ruby +Dir.glob('[k-m][h-j][a-c]') # => ["lib"] +Dir.glob('\[k-m][h-j][a-c]') # => [] # Escaped. +``` + +The range may be negated: + +```ruby +Dir.glob('[^k-m][h-j][a-c]') # => [] +Dir.glob('[^a-c][^k-m][^h-j]') # => ["GPL", "doc", "enc", "ext", "jit", "lib", "man"] +``` + +### Alternatives (`'{ , }'`) + +The alternatives pattern consists of comma-separated strings +enclosed in curly braces: + +```ruby +Dir.glob('{k,L,R}*') # => ["kernel.rb", "LEGAL", "README.ja.md", "README.md"] +Dir.glob('{R,L,k}*') # => ["README.ja.md", "README.md", "LEGAL", "kernel.rb"] +# Whitespace matters: +Dir.glob('{k ,L,R}*') # => ["LEGAL", "README.ja.md", "README.md"] +``` + +### Recursive Directory Matching (`'**'`) + +The double-asterisk pattern (`'**'`) matches directories recursively: + +```ruby +# Find all entries everywhere ending with '.ja'. +Dir.glob('**/*.ja') +# => ["COPYING.ja", "doc/pty/README.expect.ja", "doc/pty/README.ja"] + +# Find all entries everywhere ending with '.rb'. +Dir.glob('**/*.rb').size # => 7574 +Dir.glob('**/*.rb').take(3) +# => ["KNOWNBUGS.rb", "array.rb", "ast.rb"] + +# Find all entries in directory 'lib' ending with `.rb'. +Dir.glob('lib/**/*.rb').size # => 626 +Dir.glob('lib/**/*.rb').take(3) +# # => +# ["lib/English.rb", +# "lib/bundled_gems.rb", +# "lib/bundler/build_metadata.rb"] + +# Find all entries in directory 'test/ruby' ending with '.rb'. +Dir.glob('test/ruby/**/*.rb').size # => 200 +Dir.glob('test/ruby/**/*.rb').take(3) +# # => +# ["test/ruby/allpairs.rb", +# "test/ruby/beginmainend.rb", +# "test/ruby/box/a.1_1_0.rb"] + +# Escaped. +Dir.glob('\**/*.rb') # => [] +``` + + +### Escape (`'\'`) + +The backslash character (`'\'`) may be used to escape any of the characters +that filename globbing treats as special: + +```ruby +Dir.glob('\*') # => [] +Dir.glob('\?') # => [] +Dir.glob('\[efgh][abcd]') # => [] +Dir.glob('\[k-m][h-j][a-c]') # => [] +Dir.glob('\**/*.rb') # => [] +``` + +## Keyword Arguments + +| Keyword | Value | Default | Meaning | +|-------------------|--------------------------|:-------:|-----------------------------------------| +| [`base`](#base) | \String path. | `'.'` | Root for searching. | +| [`flags`](#flags) | Logical OR of constants. | `0` | Modify globbing behavior. | +| [`sort`](#sort) | `true` or `false` | `true` | Whether returned array is to be sorted. | + +### `base` + +Optional keyword argument `base` (defaults to `'.'`) +specifies where in the filesystem the searching is to begin: + +```ruby +Dir.glob('*').size # => 241 +Dir.glob('*').take(3) +# => ["BSDL", "CONTRIBUTING.md", "COPYING"] + +Dir.glob('*', base: 'lib').size # => 72 +Dir.glob('*', base: 'lib').take(3) +# => ["English.gemspec", "English.rb", "bundled_gems.rb"] + +Dir.glob('*', base: 'lib/net').size # => 5 +Dir.glob('*', base: 'lib/net').take(3) +# => ["http", "http.rb", "https.rb"] +``` + +### `flags` + +Optional keyword argument `flags` (defaults to `0`) may be the bitwise OR +of the constants `File::FNM*`: + +```ruby +Dir.glob('*', flags: File::FNM_DOTMATCH | File::FNM_NOESCAPE) +``` + +These are the constants for filename-globbing patterns; +see the sections below for details: + + +| Constant | Meaning | +|-----------------------------------------------------|--------------------------------------------| +| [`File::FNM_DOTMATCH`](#constant-filefnmdotmatch) | Make pattern `'*'` match a leading period. | +| [`File::FNM_NOESCAPE`](#constant-filefnmnoescape) | Disable escaping. | +| [`File::FNM_SHORTNAME`](#constant-filefnmshortname) | Enable short-name matching (Windows only). | + +These constants do not affect filename globbing: + +- File::FNM_CASEFOLD. +- File::FNM_EXTGLOB. +- File::FNM_PATHNAME. +- File::FNM_SYSCASE. + +#### Constant File::FNM_DOTMATCH + +By default, filename globbing does not allow patterns `'*'` and `'?'` to match a dotfile name +(i.e, an entry name beginning with a dot); +use constant [`File::FNM_DOTMATCH`](#constant-filefnmdotmatch) +to enable the match: + +```ruby +Dir.glob('*').size # => 241 +Dir.glob('*', flags: File::FNM_DOTMATCH).size # => 256 +Dir.glob('*', flags: File::FNM_DOTMATCH).take(3) # => [".", ".dir-locals.el", ".document"] +``` + +#### Constant File::FNM_NOESCAPE + +By default filename globbing has escaping enabled; +use constant [`File::FNM_NOESCAPE`](#constant-filefnmnoescape) +to disable it: + +```ruby +Dir.glob('*').size # => 241 +Dir.glob('\*').size # => 0 +``` + +#### Constant File::FNM_SHORTNAME + +By default, Windows shortname matching is disabled; +use constant [`File::FNM_SHORTNAME`](#constant-filefnmshortname) +to enable it (on Windows only). + +Using that constant allows patterns to match short names +in filename globbing on Windows, +which can be useful for compatibility with legacy applications +that rely on these short names; +see [8.3 filename](https://en.wikipedia.org/wiki/8.3_filename). +This feature helps ensure that file operations work correctly +even when dealing with files that have long names. + +### `sort` + +Optional keyword argument `sort` (defaults to `'true'`) +specifies whether the returned array is to be sorted: + +```ruby +Dir.glob('*').take(3) +# => ["BSDL", "CONTRIBUTING.md", "COPYING"] +Dir.glob('*', sort: false).take(3) +# => ["gc.rb", "yjit.rb", "iseq.h"] +``` + diff --git a/doc/file/filename_matching.md b/doc/file/filename_matching.md new file mode 100644 index 0000000000..9f13da9012 --- /dev/null +++ b/doc/file/filename_matching.md @@ -0,0 +1,356 @@ +## Filename Matching + +Filename matching is a pattern-matching feature implemented in certain Ruby methods: + +- File.fnmatch. +- Pathname#fnmatch. + +Each `fnmatch` method matches a pattern against a string _path_; +these methods operate only on strings, and do not access the file system. + +These are quite different from filename globbing methods (not discussed here), +which match patterns against string paths found in the actual file system: + +- Dir.glob. +- Pathname.glob. +- Pathname#glob. + +### Patterns + +These are the basic elements of filename matching patterns; +see the sections below for details: + +| Pattern | Meaning | Examples | +|:------------------------:|--------------------------------------------|------------------------------| +| Simple string. | Matches itself. | `'Rakefile'`, `'LEGAL'` | +| `'*'` | Matches any sequence of characters. | `'*.txt'` | +| `'?'` | Matches any single character. | `'?.txt'` | +| `'[abc]'`,<br>`'[^abc]'` | Matches a single character from a set. | `'x[abc]y'`,<br>`'x[^abc]y'` | +| `'[a-z]`',<br>`'[^a-z]'` | Matches a single character from a range. | `'x[0-9]y'`,<br>`'x[^0-9]y'` | +| `'\'` | Escapes the next character. | `'\\*'`, `'\?'` | + +There are two other patterns that are disabled by default: + +- Directory-like substring (`'**'`); + see [`File::FNM_PATHNAME`](#constant-filefnmpathname) below. +- Alternatives (`'{ , }'`); + see [`File::FNM_EXTGLOB`](#constant-filefnmextglob) below. + +#### Simple \String + +A "simple string" is one that does not contain special filename-matching patterns; +see the table above. + +A simple string matches itself: + +```ruby +File.fnmatch('xyzzy', 'xyzzy') # => true +File.fnmatch('one_two_three', 'one_two_three') # => true +File.fnmatch('123', '123') # => true +File.fnmatch('Form 27B/6', 'Form 27B/6') # => true +File.fnmatch('bcd', 'abcde') # => false # Must be exact. +``` + +By default, the matching is case-sensitive: + +```ruby +File.fnmatch('abc', 'ABC') # => false +``` + +Case-sensitivity may be modified by flags: + +- [`File::FNM_CASEFOLD`](#constant-filefnmcasefold). +- [`File::FNM_SYSCASE`](#constant-filefnmsyscase). + +By default, the alternatives pattern is disabled: + +```rutby +File.fnmatch('R{ub,foo}y', 'Ruby') # => false +``` + +It may be enabled by flag [`File::FNM_EXTGLOB`](#constant-filefnmextglob). + +By default, the Windows short name pattern is disabled: + +```ruby +File.fnmatch('PROGRAM~1', 'Program Files') # => false +``` + +It may be enabled by flag [`File::FNM_SHORTNAME`](#constant-filefnmshortname). + +#### Any Sequence of Characters (`'*'`) + +The asterisk pattern (`'*'`) matches any sequence of characters: + +```ruby +File.fnmatch('*', 'foo') # => true +File.fnmatch('*', '') # => true +File.fnmatch('*', '*') # => true +File.fnmatch('\*', 'foo') # => false # Escaped. +``` + +By default, the asterisk pattern does not match a leading period (as in a dot-file): + +```ruby +File.fnmatch('*', '.document') # => false +``` + +That matching may be enabled by flag [`File::FNM_DOTMATCH`](#constant-filefnmdotmatch). + +By default, the asterisk pattern matches across file separators: + +```ruby +File.fnmatch('*.rb', 'lib/test.rb') # => true +``` + +That matching may be disabled by flag [`File::FNM_PATHNAME`](#constant-filefnmpathname). + +#### Single Character (`'?'`) + +The question-mark pattern (`'?'`) matches any single character: + +```ruby +File.fnmatch('?', 'f') # => true +File.fnmatch("foo-?.txt", "foo-1.txt") # => true +File.fnmatch('?', 'foo') # => false +File.fnmatch('?', '') # => false +File.fnmatch('\?', 'f') # => false # Escaped. +``` + +By default, pattern `'?'` matches the file separator: + +```ruby +File.fnmatch('foo?boo', 'foo/boo') # => true +``` + +That matching may be disabled by flag [`File::FNM_PATHNAME`](#constant-filefnmpathname). + +#### Single Character from a Set (`'[abc]'`, `'[^abc]'`) + +Characters enclosed in square brackets define a set of characters, +any of which matches a single character: + +```ruby +File.fnmatch('[ruby]', 'r') # => true +File.fnmatch('[ruby]', 'u') # => true +File.fnmatch('[ruby]', 'y') # => true +File.fnmatch('[ruby]', 'ruby') # => false +File.fnmatch('\[ruby]', 'r') # => false # Escaped. +``` + +The character set may be negated: + +```ruby +File.fnmatch('[^ruby]', 'r') # => false +File.fnmatch('[^ruby]', 'u') # => false +``` + +#### Single Character from a \Range (`'[a-c]'`, `'[^a-c]'`) + +A range of characters enclosed in square brackets defines a set of characters, +any of which matches a single character: + +```ruby +File.fnmatch('[a-c]', 'b') # => true +File.fnmatch('[a-c]', 'd') # => false +File.fnmatch('[a-c]', 'abc') # => false +File.fnmatch('R[t-v][a-c]y', 'Ruby') # => true # Multiple ranges allowed. +File.fnmatch('\[a-c]', 'b') # => false # Escaped. +``` + +The range may be negated: + +```ruby +File.fnmatch('[^a-c]', 'b') # => false +File.fnmatch('[^a-c]', 'd') # => true +``` + +#### Escape (`'\'`) + +The backslash character (`'\'`) may be used to escape any of the characters +that filename matching treats as special: + +```ruby +File.fnmatch('[a-c]', 'b') # => true +File.fnmatch('\[a-c]', 'b') # => false +File.fnmatch('[a-c\]', 'b') # => false +File.fnmatch('[a\-c]', 'b') # => false + +File.fnmatch('{a,b}', 'b', File::FNM_EXTGLOB) # => true +File.fnmatch('\{a,b}', 'b', File::FNM_EXTGLOB) # => false +File.fnmatch('{a\,b}', 'b', File::FNM_EXTGLOB) # => false +File.fnmatch('{a,b\}', 'b', File::FNM_EXTGLOB) # => false +``` + +Use a double-backslash to represent an ordinary backslash: + +```ruby +File.fnmatch('\\\\', '\\') # => true +``` + +By default escape pattern `'\'` is enabled; +it may be disabled by flag [`File::FNM_NOESCAPE`](#constant-filefnmnoescape). + +### Flags + +Optional argument `flags` (defaults to `0`) may be the bitwise OR +of the constants `File::FNM*`. + +These are the constants for filename-matching patterns; +see the sections below for details: + +| Constant | Meaning | +|-----------------------------------------------------|-------------------------------------------------------------| +| [`File::FNM_CASEFOLD`](#constant-filefnmcasefold) | Make the pattern case-insensitive. | +| [`File::FNM_DOTMATCH`](#constant-filefnmdotmatch) | Make pattern `*` match a leading period.. | +| [`File::FNM_EXTGLOB`](#constant-filefnmextglob) | Enable alternatives in pattern. | +| [`File::FNM_NOESCAPE`](#constant-filefnmnoescape) | Disable escaping. | +| [`File::FNM_PATHNAME`](#constant-filefnmpathname) | Make patterns `'*'` and `'?'` not match the file separator. | +| [`File::FNM_SHORTNAME`](#constant-filefnmshortname) | Enable short-name matching (Windows only). | +| [`File::FNM_SYSCASE`](#constant-filefnmsyscase) | Make the pattern use OS's case sensitivity. | + + +#### Constant File::FNM_CASEFOLD + +By default, filename matching is case-sensitive; +use constant [`File::FNM_CASEFOLD`](#constant-filefnmcasefold) +to make the matching case-insensitive: + +```ruby +File.fnmatch('abc', 'ABC') # => false +File.fnmatch('abc', 'ABC', File::FNM_CASEFOLD) # => true +``` + +#### Constant File::FNM_DOTMATCH + +By default, filename matching does not allow pattern `'*'` to match a dotfile name +(i.e, a filename beginning with a dot); +use constant [`File::FNM_DOTMATCH`](#constant-filefnmdotmatch) +to enable the match: + +```ruby +File.fnmatch('*', '.document') # => false +File.fnmatch('*', '.document', File::FNM_DOTMATCH) # => true +``` +#### Constant File::FNM_EXTGLOB + +By default, filename matching has the alternative notation disabled; +use constant [`File::FNM_EXTGLOB`](#constant-filefnmextglob) +to enable it: + +```ruby +File.fnmatch('R{ub,foo}y', 'Ruby') # => false +File.fnmatch('R{ub,foo}y', 'Ruby', File::FNM_EXTGLOB) # => true +``` + +The alternatives pattern consists of zero or more unquoted strings, +separated by commas, and enclosed in curly braces: + +```ruby +File.fnmatch('R{ub,foo,bar}y', 'Ruby') # => false # Not enabled. +File.fnmatch('R{ub,foo,bar}y', 'Ruby', File::FNM_EXTGLOB) # => true +# Whitespace matters. +File.fnmatch('R{ub ,foo,bar}y', 'Ruby', File::FNM_EXTGLOB) # => false +File.fnmatch('R{ ub,foo,bar}y', 'Ruby', File::FNM_EXTGLOB) # => false +# Special characters remain in force: +File.fnmatch('{*,?}', 'hello', File::FNM_EXTGLOB) # => true +File.fnmatch('{*ello,?}', 'hello', File::FNM_EXTGLOB) # => true +File.fnmatch('{*ELLO,?}', 'hello', File::FNM_EXTGLOB) # => false +File.fnmatch('{*ELLO,?????}', 'hello', File::FNM_EXTGLOB) # => true +# With the flag not given. +File.fnmatch('R{ub,foo,bar}y', 'Ruby') # => false +``` + +#### Constant File::FNM_NOESCAPE + +By default filename matching has escaping enabled; +use constant [`File::FNM_NOESCAPE`](#constant-filefnmnoescape) +to disable it: + +```ruby +File.fnmatch('\*\?\*\*', '*?**') # => true +File.fnmatch('\*\?\*\*', '*?**', File::FNM_NOESCAPE) # => false +``` + +#### Constant File::FNM_PATHNAME + +Flag [`File::FNM_PATHNAME`](#constant-filefnmpathname) affects +patterns `'**'`, `'*'`, and `'?'`. + +By default, the double-asterisk pattern (`'**'`) is equivalent to pattern `'*'`, +and matches any sequence of directory-like substrings: + +```ruby +File.fnmatch('**', 'a/b/c') # => true +File.fnmatch('*', 'a/b/c') # => true +``` + +When flag [`File::FNM_PATHNAME`](#constant-filefnmpathname) is given, +the pattern matches only one component of a file path: + +```ruby +File.fnmatch('**', 'a/b/c') # => true # Matches 'a/b/c'. +File.fnmatch('**', 'a/b/c', File::FNM_PATHNAME) # => false # Matches only 'a'. +File.fnmatch('**', 'a/b/c', File::FNM_PATHNAME) # => false # Matches only 'a/b'. +File.fnmatch('**/*', 'a/b/c', File::FNM_PATHNAME) # => true # Matches 'a/b', then 'c'. +``` + +By default, filename matching enables pattern `'*'` to match +at or across the file separator (`File::SEPARATOR`); +use constant [`File::FNM_PATHNAME`](#constant-filefnmpathname) +to disable such matching: + +```ruby +File::SEPARATOR # => "/" +File.fnmatch('*.rb', 'lib/test.rb') # => true +File.fnmatch('*.rb', 'lib/test.rb', File::FNM_PATHNAME) # => false +``` + +By default, filename matching enables pattern `'?'` to match +at or across the file separator (`File::SEPARATOR`); +use constant [`File::FNM_PATHNAME`](#constant-filefnmpathname) +to disable such matching: + +```ruby +File.fnmatch('foo?boo', 'foo/boo') # => true +File.fnmatch('foo?boo', 'foo/boo', File::FNM_PATHNAME) # => false +``` + +#### Constant File::FNM_SHORTNAME + +By default, Windows shortname matching is disabled; +use constant [`File::FNM_SHORTNAME`](#constant-filefnmshortname) +to enable it (on Windows only). + +Using that constant allows patterns to match short names +in filename matching on Windows, +which can be useful for compatibility with legacy applications +that rely on these short names; +see [8.3 filename](https://en.wikipedia.org/wiki/8.3_filename). +This feature helps ensure that file operations work correctly +even when dealing with files that have long names. + +```ruby +File::FNM_SHORTNAME.zero? # => false # On Windows, not zero; may be enabled. +File::FNM_SHORTNAME.zero? # => true # Elsewhere, always zero; may not be enabled. + +File.fnmatch('PROGRAM~1', 'Program Files') # => false +# This will be true if and only if on Windows and short name 'PROGRAM~1' exists. +File.fnmatch('PROGRAM~1', 'Program Files', File::FNM_SHORTNAME) # => true +``` + +#### Constant File::FNM_SYSCASE + +By default, filename matching uses Ruby's own case-sensitivity rules; +use constant [`File::FNM_SYSCASE`](#constant-filefnmsyscase) +to use the case-sensitivity rules of the underlying file system: + +```ruby +File::FNM_SYSCASE.zero? # => false # On Windows, not zero; may be enabled. +File::FNM_SYSCASE.zero? # => true # Elsewhere, always zero; may not be enabled. + +File.fnmatch('abc', 'ABC') # => false # Ruby; case-sensitive. +File.fnmatch('abc', 'ABC', File::FNM_SYSCASE) # => true # Windows; case-insensitive. +File.fnmatch('abc', 'ABC', File::FNM_SYSCASE) # => false # Linus; case-sensitive. +``` + diff --git a/doc/file/timestamps.md b/doc/file/timestamps.md new file mode 100644 index 0000000000..c8ad616567 --- /dev/null +++ b/doc/file/timestamps.md @@ -0,0 +1,83 @@ +# \File System Timestamps + +A file system entry (the name of a file or directory) +has several times (called timestamps) associated with it. + +The Ruby methods that return these timestamps (each as a Time object) +are actually returning "whatever the OS says," +and so their behaviors may vary among OS platforms. +If a platform does not support a particular timestamp, +the corresponding Ruby methods raise NotImplementedError. + +These timestamps are: + +| Name | Meaning | Changes | +|:--------------------------------:|----------------------------------------|-----------------------| +| [`birthtime`](#birth-time) | Create time. | Never. | +| [`mtime`](#modification-time) | Modification time. | When written. | +| [`atime`](#access-time) | Access time. | When read or written. | +| [`ctime`](#metadata-change-time) | Metadata-change time (or create time). | See below. | + +## Birth \Time + +The birth time for an entry is the time the entry was created. +The birth time does not change, although if the entry is deleted and re-created, +the birth time will be different. + +Each of these methods returns the birth time for an entry as a Time object: + +- File::birthtime. +- File#birthtime. +- File::Stat#birthtime. +- Pathname#birthtime. + +On Windows, each of these methods also returns the birth time: + +- File::ctime. +- File#ctime. +- File::Stat#ctime. +- Pathname#ctime. + +## Modification \Time + +The modification time for an entry is the time the entry was last modified. +The modification time is updated when the entry is written, +though some file systems may delay the update. + +Each of these methods returns the modification time for an entry as a Time object: + +- File::mtime. +- File#mtime. +- File::Stat#mtime. +- Pathname#mtime. + +## Access \Time + +The access time for an entry is the time the entry last read. +The access time is updated when the entry is read, +though some file systems may delay the update. + +Each of these methods returns the access time for an entry as a Time object: + +- File::atime. +- File#atime. +- File::Stat#atime. +- Pathname#atime. + +## Metadata-Change \Time + +The metadata-change time for an entry is the time the entry last read. +The metadata-change time is updated when the entry's metadata is changed; +changing access mode or permissions may update the metadata-change time, +though some file systems may delay the update. + +On non-Windows systems, +each of these methods returns the metadata-change time for an entry: + +- File::ctime. +- File#ctime. +- File::Stat#ctime. +- Pathname#ctime. + +On Windows, each `ctime` method returns the birth time, +not the metadata-change time. |
