[rubygems/rubygems] Use a constant empty tar header to avoid extra allocations
[ruby.git] / dir.rb
blob42b475ab2cd82c5a9ac9a4e84e784969fb813b36
1 # An object of class \Dir represents a directory in the underlying file system.
3 # It consists mainly of:
5 # - A string _path_, given when the object is created,
6 #   that specifies a directory in the underlying file system;
7 #   method #path returns the path.
8 # - A collection of string <i>entry names</i>,
9 #   each of which is the name of a directory or file in the underlying file system;
10 #   the entry names may be retrieved
11 #   in an {array-like fashion}[rdoc-ref:Dir@Dir+As+Array-Like]
12 #   or in a {stream-like fashion}[rdoc-ref:Dir@Dir+As+Stream-Like].
14 # == About the Examples
16 # Some examples on this page use this simple file tree:
18 #   example/
19 #   ├── config.h
20 #   ├── lib/
21 #   │   ├── song/
22 #   │   │   └── karaoke.rb
23 #   │   └── song.rb
24 #   └── main.rb
26 # Others use the file tree for the
27 # {Ruby project itself}[https://github.com/ruby/ruby].
29 # == \Dir As \Array-Like
31 # A \Dir object is in some ways array-like:
33 # - It has instance methods #children, #each, and #each_child.
34 # - It includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here].
36 # == \Dir As Stream-Like
38 # A \Dir object is in some ways stream-like.
40 # The stream is initially open for reading,
41 # but may be closed manually (using method #close),
42 # and will be closed on block exit if created by Dir.open called with a block.
43 # The closed stream may not be further manipulated,
44 # and may not be reopened.
46 # The stream has a _position_, which is the index of an entry in the directory:
48 # - The initial position is zero (before the first entry).
49 # - \Method #tell (aliased as #pos) returns the position.
50 # - \Method #pos= sets the position (but ignores a value outside the stream),
51 #   and returns the position.
52 # - \Method #seek is like #pos=, but returns +self+ (convenient for chaining).
53 # - \Method #read, if not at end-of-stream, reads the next entry and increments
54 #   the position;
55 #   if at end-of-stream, does not increment the position.
56 # - \Method #rewind sets the position to zero.
58 # Examples (using the {simple file tree}[rdoc-ref:Dir@About+the+Examples]):
60 #   dir = Dir.new('example') # => #<Dir:example>
61 #   dir.pos                  # => 0
63 #   dir.read # => "."
64 #   dir.read # => ".."
65 #   dir.read # => "config.h"
66 #   dir.read # => "lib"
67 #   dir.read # => "main.rb"
68 #   dir.pos  # => 5
69 #   dir.read # => nil
70 #   dir.pos  # => 5
72 #   dir.rewind # => #<Dir:example>
73 #   dir.pos    # => 0
75 #   dir.pos = 3 # => 3
76 #   dir.pos     # => 3
78 #   dir.seek(4) # => #<Dir:example>
79 #   dir.pos     # => 4
81 #   dir.close # => nil
82 #   dir.read  # Raises IOError.
84 # == What's Here
86 # First, what's elsewhere. \Class \Dir:
88 # - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
89 # - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
90 #   which provides dozens of additional methods.
92 # Here, class \Dir provides methods that are useful for:
94 # - {Reading}[rdoc-ref:Dir@Reading]
95 # - {Setting}[rdoc-ref:Dir@Setting]
96 # - {Querying}[rdoc-ref:Dir@Querying]
97 # - {Iterating}[rdoc-ref:Dir@Iterating]
98 # - {Other}[rdoc-ref:Dir@Other]
100 # === Reading
102 # - #close: Closes the directory stream for +self+.
103 # - #pos=: Sets the position in the directory stream for +self+.
104 # - #read: Reads and returns the next entry in the directory stream for +self+.
105 # - #rewind: Sets the position in the directory stream for +self+ to the first entry.
106 # - #seek: Sets the position in the directory stream for +self+
107 #   the entry at the given offset.
109 # === Setting
111 # - ::chdir: Changes the working directory of the current process
112 #   to the given directory.
113 # - ::chroot: Changes the file-system root for the current process
114 #   to the given directory.
116 # === Querying
118 # - ::[]: Same as ::glob without the ability to pass flags.
119 # - ::children: Returns an array of names of the children
120 #   (both files and directories) of the given directory,
121 #   but not including <tt>.</tt> or <tt>..</tt>.
122 # - ::empty?: Returns whether the given path is an empty directory.
123 # - ::entries: Returns an array of names of the children
124 #   (both files and directories) of the given directory,
125 #   including <tt>.</tt> and <tt>..</tt>.
126 # - ::exist?: Returns whether the given path is a directory.
127 # - ::getwd (aliased as #pwd): Returns the path to the current working directory.
128 # - ::glob: Returns an array of file paths matching the given pattern and flags.
129 # - ::home: Returns the home directory path for a given user or the current user.
130 # - #children: Returns an array of names of the children
131 #   (both files and directories) of +self+,
132 #   but not including <tt>.</tt> or <tt>..</tt>.
133 # - #fileno: Returns the integer file descriptor for +self+.
134 # - #path (aliased as #to_path): Returns the path used to create +self+.
135 # - #tell (aliased as #pos): Returns the integer position
136 #   in the directory stream for +self+.
138 # === Iterating
140 # - ::each_child: Calls the given block with each entry in the given directory,
141 #   but not including <tt>.</tt> or <tt>..</tt>.
142 # - ::foreach: Calls the given block with each entry in the given directory,
143 #   including <tt>.</tt> and <tt>..</tt>.
144 # - #each: Calls the given block with each entry in +self+,
145 #   including <tt>.</tt> and <tt>..</tt>.
146 # - #each_child: Calls the given block with each entry in +self+,
147 #   but not including <tt>.</tt> or <tt>..</tt>.
149 # === Other
151 # - ::mkdir: Creates a directory at the given path, with optional permissions.
152 # - ::new: Returns a new \Dir for the given path, with optional encoding.
153 # - ::open: Same as ::new, but if a block is given, yields the \Dir to the block,
154 #   closing it upon block exit.
155 # - ::unlink (aliased as ::delete and ::rmdir): Removes the given directory.
156 # - #inspect: Returns a string description of +self+.
158 class Dir
159   # call-seq:
160   #   Dir.open(dirpath) -> dir
161   #   Dir.open(dirpath, encoding: nil) -> dir
162   #   Dir.open(dirpath) {|dir| ... } -> object
163   #   Dir.open(dirpath, encoding: nil) {|dir| ... } -> object
164   #
165   # Creates a new \Dir object _dir_ for the directory at +dirpath+.
166   #
167   # With no block, the method equivalent to Dir.new(dirpath, encoding):
168   #
169   #   Dir.open('.') # => #<Dir:.>
170   #
171   # With a block given, the block is called with the created _dir_;
172   # on block exit _dir_ is closed and the block's value is returned:
173   #
174   #   Dir.open('.') {|dir| dir.inspect } # => "#<Dir:.>"
175   #
176   # The value given with optional keyword argument +encoding+
177   # specifies the encoding for the directory entry names;
178   # if +nil+ (the default), the file system's encoding is used:
179   #
180   #   Dir.open('.').read.encoding                       # => #<Encoding:UTF-8>
181   #   Dir.open('.', encoding: 'US-ASCII').read.encoding # => #<Encoding:US-ASCII>
182   #
183   def self.open(name, encoding: nil, &block)
184     dir = Primitive.dir_s_open(name, encoding)
185     if block
186       begin
187         yield dir
188       ensure
189         Primitive.dir_s_close(dir)
190       end
191     else
192       dir
193     end
194   end
196   # call-seq:
197   #   Dir.new(dirpath) -> dir
198   #   Dir.new(dirpath, encoding: nil) -> dir
199   #
200   # Returns a new \Dir object for the directory at +dirpath+:
201   #
202   #   Dir.new('.') # => #<Dir:.>
203   #
204   # The value given with optional keyword argument +encoding+
205   # specifies the encoding for the directory entry names;
206   # if +nil+ (the default), the file system's encoding is used:
207   #
208   #   Dir.new('.').read.encoding                       # => #<Encoding:UTF-8>
209   #   Dir.new('.', encoding: 'US-ASCII').read.encoding # => #<Encoding:US-ASCII>
210   #
211   def initialize(name, encoding: nil)
212     Primitive.dir_initialize(name, encoding)
213   end
215   # call-seq:
216   #   Dir[*patterns, base: nil, sort: true] -> array
217   #
218   # Calls Dir.glob with argument +patterns+
219   # and the values of keyword arguments +base+ and +sort+;
220   # returns the array of selected entry names.
221   #
222   def self.[](*args, base: nil, sort: true)
223     Primitive.dir_s_aref(args, base, sort)
224   end
226   # call-seq:
227   #   Dir.glob(*patterns, flags: 0, base: nil, sort: true) -> array
228   #   Dir.glob(*patterns, flags: 0, base: nil, sort: true) {|entry_name| ... } -> nil
229   #
230   # Forms an array _entry_names_ of the entry names selected by the arguments.
231   #
232   # Argument +patterns+ is a string pattern or an array of string patterns;
233   # note that these are not regexps; see below.
234   #
235   # Notes for the following examples:
236   #
237   # - <tt>'*'</tt> is the pattern that matches any entry name
238   #   except those that begin with <tt>'.'</tt>.
239   # - We use method Array#take to shorten returned arrays
240   #   that otherwise would be very large.
241   #
242   # With no block, returns array _entry_names_;
243   # example (using the {simple file tree}[rdoc-ref:Dir@About+the+Examples]):
244   #
245   #   Dir.glob('*') # => ["config.h", "lib", "main.rb"]
246   #
247   # With a block, calls the block with each of the _entry_names_
248   # and returns +nil+:
249   #
250   #   Dir.glob('*') {|entry_name| puts entry_name } # => nil
251   #
252   # Output:
253   #
254   #   config.h
255   #   lib
256   #   main.rb
257   #
258   # If optional keyword argument +flags+ is given,
259   # the value modifies the matching; see below.
260   #
261   # If optional keyword argument +base+ is given,
262   # its value specifies the base directory.
263   # Each pattern string specifies entries relative to the base directory;
264   # the default is <tt>'.'</tt>.
265   # The base directory is not prepended to the entry names in the result:
266   #
267   #   Dir.glob(pattern, base: 'lib').take(5)
268   #   # => ["abbrev.gemspec", "abbrev.rb", "base64.gemspec", "base64.rb", "benchmark.gemspec"]
269   #   Dir.glob(pattern, base: 'lib/irb').take(5)
270   #   # => ["cmd", "color.rb", "color_printer.rb", "completion.rb", "context.rb"]
271   #
272   # If optional keyword +sort+ is given, its value specifies whether
273   # the array is to be sorted; the default is +true+.
274   # Passing value +false+ with that keyword disables sorting
275   # (though the underlying file system may already have sorted the array).
276   #
277   # <b>Patterns</b>
278   #
279   # Each pattern string is expanded
280   # according to certain metacharacters;
281   # examples below use the {Ruby file tree}[rdoc-ref:Dir@About+the+Examples]:
282   #
283   # - <tt>'*'</tt>: Matches any substring in an entry name,
284   #   similar in meaning to regexp <tt>/.*/mx</tt>;
285   #   may be restricted by other values in the pattern strings:
286   #
287   #   - <tt>'*'</tt> matches all entry names:
288   #
289   #       Dir.glob('*').take(3)  # => ["BSDL", "CONTRIBUTING.md", "COPYING"]
290   #
291   #   - <tt>'c*'</tt> matches entry names beginning with <tt>'c'</tt>:
292   #
293   #       Dir.glob('c*').take(3) # => ["CONTRIBUTING.md", "COPYING", "COPYING.ja"]
294   #
295   #   - <tt>'*c'</tt> matches entry names ending with <tt>'c'</tt>:
296   #
297   #       Dir.glob('*c').take(3) # => ["addr2line.c", "array.c", "ast.c"]
298   #
299   #   - <tt>'\*c\*'</tt> matches entry names that contain <tt>'c'</tt>,
300   #     even at the beginning or end:
301   #
302   #       Dir.glob('*c*').take(3) # => ["CONTRIBUTING.md", "COPYING", "COPYING.ja"]
303   #
304   #   Does not match Unix-like hidden entry names ("dot files").
305   #   To include those in the matched entry names,
306   #   use flag IO::FNM_DOTMATCH or something like <tt>'{*,.*}'</tt>.
307   #
308   #  - <tt>'**'</tt>: Matches entry names recursively
309   #    if followed by  the slash character <tt>'/'</tt>:
310   #
311   #      Dir.glob('**/').take(3) # => ["basictest/", "benchmark/", "benchmark/gc/"]
312   #
313   #    If the string pattern contains other characters
314   #    or is not followed by a slash character,
315   #    it is equivalent to <tt>'*'</tt>.
316   #
317   # - <tt>'?'</tt> Matches any single character;
318   #   similar in meaning to regexp <tt>/./</tt>:
319   #
320   #     Dir.glob('io.?') # => ["io.c"]
321   #
322   # - <tt>'[_set_]'</tt>: Matches any one character in the string _set_;
323   #   behaves like a {Regexp character class}[rdoc-ref:Regexp@Character+Classes],
324   #   including set negation (<tt>'[^a-z]'</tt>):
325   #
326   #     Dir.glob('*.[a-z][a-z]').take(3)
327   #     # => ["CONTRIBUTING.md", "COPYING.ja", "KNOWNBUGS.rb"]
328   #
329   # - <tt>'{_abc_,_xyz_}'</tt>:
330   #   Matches either string _abc_ or string _xyz_;
331   #   behaves like {Regexp alternation}[rdoc-ref:Regexp@Alternation]:
332   #
333   #     Dir.glob('{LEGAL,BSDL}') # => ["LEGAL", "BSDL"]
334   #
335   #   More than two alternatives may be given.
336   #
337   # - <tt>\\</tt>: Escapes the following metacharacter.
338   #
339   #   Note that on Windows, the backslash character may not be used
340   #   in a string pattern:
341   #   <tt>Dir['c:\\foo*']</tt> will not work, use <tt>Dir['c:/foo*']</tt> instead.
342   #
343   # More examples (using the {simple file tree}[rdoc-ref:Dir@About+the+Examples]):
344   #
345   #   # We're in the example directory.
346   #   File.basename(Dir.pwd) # => "example"
347   #   Dir.glob('config.?')              # => ["config.h"]
348   #   Dir.glob('*.[a-z][a-z]')          # => ["main.rb"]
349   #   Dir.glob('*.[^r]*')               # => ["config.h"]
350   #   Dir.glob('*.{rb,h}')              # => ["main.rb", "config.h"]
351   #   Dir.glob('*')                     # => ["config.h", "lib", "main.rb"]
352   #   Dir.glob('*', File::FNM_DOTMATCH) # => [".", "config.h", "lib", "main.rb"]
353   #   Dir.glob(["*.rb", "*.h"])         # => ["main.rb", "config.h"]
354   #
355   #   Dir.glob('**/*.rb')
356   #   => ["lib/song/karaoke.rb", "lib/song.rb", "main.rb"]
357   #
358   #   Dir.glob('**/*.rb', base: 'lib')  #   => ["song/karaoke.rb", "song.rb"]
359   #
360   #   Dir.glob('**/lib')                # => ["lib"]
361   #
362   #   Dir.glob('**/lib/**/*.rb')        # => ["lib/song/karaoke.rb", "lib/song.rb"]
363   #
364   #   Dir.glob('**/lib/*.rb')           # => ["lib/song.rb"]
365   #
366   # <b>Flags</b>
367   #
368   # If optional keyword argument +flags+ is given (the default is zero -- no flags),
369   # its value should be the bitwise OR of one or more of the constants
370   # defined in module File::Constants.
371   #
372   # Example:
373   #
374   #   flags = File::FNM_EXTGLOB | File::FNM_DOTMATCH
375   #
376   # Specifying flags can extend, restrict, or otherwise modify the matching.
377   #
378   # The flags for this method (other constants in File::Constants do not apply):
379   #
380   # - File::FNM_DOTMATCH:
381   #   specifies that entry names beginning with <tt>'.'</tt>
382   #   should be considered for matching:
383   #
384   #     Dir.glob('*').take(5)
385   #     # => ["BSDL", "CONTRIBUTING.md", "COPYING", "COPYING.ja", "GPL"]
386   #     Dir.glob('*', flags: File::FNM_DOTMATCH).take(5)
387   #     # => [".", ".appveyor.yml", ".cirrus.yml", ".dir-locals.el", ".document"]
388   #
389   # - File::FNM_EXTGLOB:
390   #   enables the pattern extension
391   #   <tt>'{_a_,_b_}'</tt>, which matches pattern _a_ and pattern _b_;
392   #   behaves like a
393   #   {regexp union}[rdoc-ref:Regexp.union]
394   #   (e.g., <tt>'(?:_a_|_b_)'</tt>):
395   #
396   #     pattern = '{LEGAL,BSDL}'
397   #     Dir.glob(pattern)      # => ["LEGAL", "BSDL"]
398   #
399   # - File::FNM_NOESCAPE:
400   #   specifies that escaping with the backslash character <tt>'\'</tt>
401   #   is disabled; the character is not an escape character.
402   #
403   # - File::FNM_PATHNAME:
404   #   specifies that metacharacters <tt>'*'</tt> and <tt>'?'</tt>
405   #   do not match directory separators.
406   #
407   # - File::FNM_SHORTNAME:
408   #   specifies that patterns may match short names if they exist; Windows only.
409   #
410   def self.glob(pattern, _flags = 0, flags: _flags, base: nil, sort: true)
411     Primitive.attr! :use_block
412     Primitive.dir_s_glob(pattern, flags, base, sort)
413   end
416 class << File
417   # call-seq:
418   #    File.fnmatch( pattern, path, [flags] ) -> (true or false)
419   #    File.fnmatch?( pattern, path, [flags] ) -> (true or false)
420   #
421   # Returns true if +path+ matches against +pattern+.  The pattern is not a
422   # regular expression; instead it follows rules similar to shell filename
423   # globbing.  It may contain the following metacharacters:
424   #
425   # <code>*</code>::
426   #   Matches any file. Can be restricted by other values in the glob.
427   #   Equivalent to <code>/.*/x</code> in regexp.
428   #
429   #   <code>*</code>::    Matches all regular files
430   #   <code>c*</code>::   Matches all files beginning with <code>c</code>
431   #   <code>*c</code>::   Matches all files ending with <code>c</code>
432   #   <code>\*c*</code>:: Matches all files that have <code>c</code> in them
433   #                       (including at the beginning or end).
434   #
435   #   To match hidden files (that start with a <code>.</code>) set the
436   #   File::FNM_DOTMATCH flag.
437   #
438   # <code>**</code>::
439   #   Matches directories recursively or files expansively.
440   #
441   # <code>?</code>::
442   #   Matches any one character. Equivalent to <code>/.{1}/</code> in regexp.
443   #
444   # <code>[set]</code>::
445   #   Matches any one character in +set+.  Behaves exactly like character sets
446   #   in Regexp, including set negation (<code>[^a-z]</code>).
447   #
448   # <code>\\</code>::
449   #   Escapes the next metacharacter.
450   #
451   # <code>{a,b}</code>::
452   #   Matches pattern a and pattern b if File::FNM_EXTGLOB flag is enabled.
453   #   Behaves like a Regexp union (<code>(?:a|b)</code>).
454   #
455   # +flags+ is a bitwise OR of the <code>FNM_XXX</code> constants. The same
456   # glob pattern and flags are used by Dir::glob.
457   #
458   # Examples:
459   #
460   #    File.fnmatch('cat',       'cat')        #=> true  # match entire string
461   #    File.fnmatch('cat',       'category')   #=> false # only match partial string
462   #
463   #    File.fnmatch('c{at,ub}s', 'cats')                    #=> false # { } isn't supported by default
464   #    File.fnmatch('c{at,ub}s', 'cats', File::FNM_EXTGLOB) #=> true  # { } is supported on FNM_EXTGLOB
465   #
466   #    File.fnmatch('c?t',     'cat')          #=> true  # '?' match only 1 character
467   #    File.fnmatch('c??t',    'cat')          #=> false # ditto
468   #    File.fnmatch('c*',      'cats')         #=> true  # '*' match 0 or more characters
469   #    File.fnmatch('c*t',     'c/a/b/t')      #=> true  # ditto
470   #    File.fnmatch('ca[a-z]', 'cat')          #=> true  # inclusive bracket expression
471   #    File.fnmatch('ca[^t]',  'cat')          #=> false # exclusive bracket expression ('^' or '!')
472   #
473   #    File.fnmatch('cat', 'CAT')                     #=> false # case sensitive
474   #    File.fnmatch('cat', 'CAT', File::FNM_CASEFOLD) #=> true  # case insensitive
475   #    File.fnmatch('cat', 'CAT', File::FNM_SYSCASE)  #=> true or false # depends on the system default
476   #
477   #    File.fnmatch('?',   '/', File::FNM_PATHNAME)  #=> false # wildcard doesn't match '/' on FNM_PATHNAME
478   #    File.fnmatch('*',   '/', File::FNM_PATHNAME)  #=> false # ditto
479   #    File.fnmatch('[/]', '/', File::FNM_PATHNAME)  #=> false # ditto
480   #
481   #    File.fnmatch('\?',   '?')                       #=> true  # escaped wildcard becomes ordinary
482   #    File.fnmatch('\a',   'a')                       #=> true  # escaped ordinary remains ordinary
483   #    File.fnmatch('\a',   '\a', File::FNM_NOESCAPE)  #=> true  # FNM_NOESCAPE makes '\' ordinary
484   #    File.fnmatch('[\?]', '?')                       #=> true  # can escape inside bracket expression
485   #
486   #    File.fnmatch('*',   '.profile')                      #=> false # wildcard doesn't match leading
487   #    File.fnmatch('*',   '.profile', File::FNM_DOTMATCH)  #=> true  # period by default.
488   #    File.fnmatch('.*',  '.profile')                      #=> true
489   #
490   #    File.fnmatch('**/*.rb', 'main.rb')                  #=> false
491   #    File.fnmatch('**/*.rb', './main.rb')                #=> false
492   #    File.fnmatch('**/*.rb', 'lib/song.rb')              #=> true
493   #    File.fnmatch('**.rb', 'main.rb')                    #=> true
494   #    File.fnmatch('**.rb', './main.rb')                  #=> false
495   #    File.fnmatch('**.rb', 'lib/song.rb')                #=> true
496   #    File.fnmatch('*',     'dave/.profile')              #=> true
497   #
498   #    File.fnmatch('**/foo', 'a/b/c/foo', File::FNM_PATHNAME)     #=> true
499   #    File.fnmatch('**/foo', '/a/b/c/foo', File::FNM_PATHNAME)    #=> true
500   #    File.fnmatch('**/foo', 'c:/a/b/c/foo', File::FNM_PATHNAME)  #=> true
501   #    File.fnmatch('**/foo', 'a/.b/c/foo', File::FNM_PATHNAME)    #=> false
502   #    File.fnmatch('**/foo', 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
503   def fnmatch(pattern, path, flags = 0)
504   end
505   alias fnmatch? fnmatch
506 end if false