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:
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
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>
65 # dir.read # => "config.h"
67 # dir.read # => "main.rb"
72 # dir.rewind # => #<Dir:example>
78 # dir.seek(4) # => #<Dir:example>
82 # dir.read # Raises IOError.
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]
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.
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.
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+.
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>.
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+.
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
165 # Creates a new \Dir object _dir_ for the directory at +dirpath+.
167 # With no block, the method equivalent to Dir.new(dirpath, encoding):
169 # Dir.open('.') # => #<Dir:.>
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:
174 # Dir.open('.') {|dir| dir.inspect } # => "#<Dir:.>"
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:
180 # Dir.open('.').read.encoding # => #<Encoding:UTF-8>
181 # Dir.open('.', encoding: 'US-ASCII').read.encoding # => #<Encoding:US-ASCII>
183 def self.open(name, encoding: nil, &block)
184 dir = Primitive.dir_s_open(name, encoding)
189 Primitive.dir_s_close(dir)
197 # Dir.new(dirpath) -> dir
198 # Dir.new(dirpath, encoding: nil) -> dir
200 # Returns a new \Dir object for the directory at +dirpath+:
202 # Dir.new('.') # => #<Dir:.>
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:
208 # Dir.new('.').read.encoding # => #<Encoding:UTF-8>
209 # Dir.new('.', encoding: 'US-ASCII').read.encoding # => #<Encoding:US-ASCII>
211 def initialize(name, encoding: nil)
212 Primitive.dir_initialize(name, encoding)
216 # Dir[*patterns, base: nil, sort: true] -> array
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.
222 def self.[](*args, base: nil, sort: true)
223 Primitive.dir_s_aref(args, base, sort)
227 # Dir.glob(*patterns, flags: 0, base: nil, sort: true) -> array
228 # Dir.glob(*patterns, flags: 0, base: nil, sort: true) {|entry_name| ... } -> nil
230 # Forms an array _entry_names_ of the entry names selected by the arguments.
232 # Argument +patterns+ is a string pattern or an array of string patterns;
233 # note that these are not regexps; see below.
235 # Notes for the following examples:
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.
242 # With no block, returns array _entry_names_;
243 # example (using the {simple file tree}[rdoc-ref:Dir@About+the+Examples]):
245 # Dir.glob('*') # => ["config.h", "lib", "main.rb"]
247 # With a block, calls the block with each of the _entry_names_
250 # Dir.glob('*') {|entry_name| puts entry_name } # => nil
258 # If optional keyword argument +flags+ is given,
259 # the value modifies the matching; see below.
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:
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"]
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).
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]:
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:
287 # - <tt>'*'</tt> matches all entry names:
289 # Dir.glob('*').take(3) # => ["BSDL", "CONTRIBUTING.md", "COPYING"]
291 # - <tt>'c*'</tt> matches entry names beginning with <tt>'c'</tt>:
293 # Dir.glob('c*').take(3) # => ["CONTRIBUTING.md", "COPYING", "COPYING.ja"]
295 # - <tt>'*c'</tt> matches entry names ending with <tt>'c'</tt>:
297 # Dir.glob('*c').take(3) # => ["addr2line.c", "array.c", "ast.c"]
299 # - <tt>'\*c\*'</tt> matches entry names that contain <tt>'c'</tt>,
300 # even at the beginning or end:
302 # Dir.glob('*c*').take(3) # => ["CONTRIBUTING.md", "COPYING", "COPYING.ja"]
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>.
308 # - <tt>'**'</tt>: Matches entry names recursively
309 # if followed by the slash character <tt>'/'</tt>:
311 # Dir.glob('**/').take(3) # => ["basictest/", "benchmark/", "benchmark/gc/"]
313 # If the string pattern contains other characters
314 # or is not followed by a slash character,
315 # it is equivalent to <tt>'*'</tt>.
317 # - <tt>'?'</tt> Matches any single character;