class Dir - RDoc Documentation

# class Dir

An object of class Dir represents a directory in the underlying file system.

It consists mainly of:

- A string path, given when the object is created, that specifies a directory in the underlying file system; method `path` returns the path.

- A collection of string entry names, each of which is the name of a directory or file in the underlying file system; the entry names may be retrieved in an array-like fashion or in a stream-like fashion.

## About the Examples¶ ↑

Some examples on this page use this simple file tree:

    example/
    ├── config.h
    ├── lib/
    │   ├── song/
    │   │   └── karaoke.rb
    │   └── song.rb
    └── main.rb

Others use the file tree for the Ruby project itself.

## Dir As Array-Like¶ ↑

A Dir object is in some ways array-like:

- It has instance methods `children`, `each`, and `each_child`.

- It includes module Enumerable.

## Dir As Stream-Like¶ ↑

A Dir object is in some ways stream-like.

The stream is initially open for reading, but may be closed manually (using method `close`), and will be closed on block exit if created by `Dir.open` called with a block. The closed stream may not be further manipulated, and may not be reopened.

The stream has a position, which is the index of an entry in the directory:

- The initial position is zero (before the first entry).

- Method `tell` (aliased as `pos`) returns the position.

- Method `pos=` sets the position (but ignores a value outside the stream), and returns the position.

- Method `seek` is like `pos=`, but returns `self` (convenient for chaining).

- Method `read`, if not at end-of-stream, reads the next entry and increments the position; if at end-of-stream, does not increment the position.

- Method `rewind` sets the position to zero.

Examples (using the simple file tree):

    dir = Dir.new('example') # => #<Dir:example>
    dir.pos                  # => 0

    dir.read # => "."
    dir.read # => ".."
    dir.read # => "config.h"
    dir.read # => "lib"
    dir.read # => "main.rb"
    dir.pos  # => 5
    dir.read # => nil
    dir.pos  # => 5

    dir.rewind # => #<Dir:example>
    dir.pos    # => 0

    dir.pos = 3 # => 3
    dir.pos     # => 3

    dir.seek(4) # => #<Dir:example>
    dir.pos     # => 4

    dir.close # => nil
    dir.read  # Raises IOError.

## What’s Here¶ ↑

First, what’s elsewhere. Class Dir:

- Inherits from class Object.

- Includes module Enumerable, which provides dozens of additional methods.

Here, class Dir provides methods that are useful for:

- Reading

- Setting

- Querying

- Iterating

- Other

### Reading¶ ↑

- `close`: Closes the directory stream for `self`.

- `pos=`: Sets the position in the directory stream for `self`.

- `read`: Reads and returns the next entry in the directory stream for `self`.

- `rewind`: Sets the position in the directory stream for `self` to the first entry.

- `seek`: Sets the position in the directory stream for `self` the entry at the given offset.

### Setting¶ ↑

- `::chdir`: Changes the working directory of the current process to the given directory.

- `::chroot`: Changes the file-system root for the current process to the given directory.

### Querying¶ ↑

- `::[]`: Same as `::glob` without the ability to pass flags.

- `::children`: Returns an array of names of the children (both files and directories) of the given directory, but not including `.` or `..`.

- `::empty?`: Returns whether the given path is an empty directory.

- `::entries`: Returns an array of names of the children (both files and directories) of the given directory, including `.` and `..`.

- `::exist?`: Returns whether the given path is a directory.

- `::getwd` (aliased as pwd): Returns the path to the current working directory.

- `::glob`: Returns an array of file paths matching the given pattern and flags.

- `::home`: Returns the home directory path for a given user or the current user.

- `children`: Returns an array of names of the children (both files and directories) of `self`, but not including `.` or `..`.

- `fileno`: Returns the integer file descriptor for `self`.

- `path` (aliased as `to_path`): Returns the path used to create `self`.

- `tell` (aliased as `pos`): Returns the integer position in the directory stream for `self`.

### Iterating¶ ↑

- `::each_child`: Calls the given block with each entry in the given directory, but not including `.` or `..`.

- `::foreach`: Calls the given block with each entry in the given directory, including `.` and `..`.

- `each`: Calls the given block with each entry in `self`, including `.` and `..`.

- `each_child`: Calls the given block with each entry in `self`, but not including `.` or `..`.

### Other¶ ↑

- `::mkdir`: Creates a directory at the given path, with optional permissions.

- `::new`: Returns a new Dir for the given path, with optional encoding.

- `::open`: Same as `::new`, but if a block is given, yields the Dir to the block, closing it upon block exit.

- `::unlink` (aliased as `::delete` and `::rmdir`): Removes the given directory.

- `inspect`: Returns a string description of `self`.

### Public Class Methods

Dir[*patterns, base: nil, sort: true] → array click to toggle source

Calls `Dir.glob` with argument `patterns` and the values of keyword arguments `base` and `sort`; returns the array of selected entry names.

    # File ruby_3_4_1/dir.rb, line 222
    def self.[](*args, base: nil, sort: true)
      Primitive.dir_s_aref(args, base, sort)
    end

chdir(new_dirpath) → 0 click to toggle source
chdir → 0
chdir(new_dirpath) {|new_dirpath| ... } → object
chdir {|cur_dirpath| ... } → object

Changes the current working directory.

With argument `new_dirpath` and no block, changes to the given `dirpath`:

    Dir.pwd         # => "/example"
    Dir.chdir('..') # => 0
    Dir.pwd         # => "/"

With no argument and no block:

- Changes to the value of environment variable `HOME` if defined.

- Otherwise changes to the value of environment variable `LOGDIR` if defined.

- Otherwise makes no change.

With argument `new_dirpath` and a block, temporarily changes the working directory:

- Calls the block with the argument.

- Changes to the given directory.

- Executes the block (yielding the new path).

- Restores the previous working directory.

- Returns the block’s return value.

Example:

    Dir.chdir('/var/spool/mail')
    Dir.pwd   # => "/var/spool/mail"
    Dir.chdir('/tmp') do
      Dir.pwd # => "/tmp"
    end
    Dir.pwd   # => "/var/spool/mail"

With no argument and a block, calls the block with the current working directory (string) and returns the block’s return value.

Calls to Dir.chdir with blocks may be nested:

    Dir.chdir('/var/spool/mail')
    Dir.pwd     # => "/var/spool/mail"
    Dir.chdir('/tmp') do
      Dir.pwd   # => "/tmp"
      Dir.chdir('/usr') do
        Dir.pwd # => "/usr"
      end
      Dir.pwd   # => "/tmp"
    end
    Dir.pwd     # => "/var/spool/mail"

In a multi-threaded program an error is raised if a thread attempts to open a `chdir` block while another thread has one open, or a call to `chdir` without a block occurs inside a block passed to `chdir` (even in the same thread).

Raises an exception if the target directory does not exist.

    static VALUE
    dir_s_chdir(int argc, VALUE *argv, VALUE obj)
    {
        VALUE path = Qnil;

        if (rb_check_arity(argc, 0, 1) == 1) {
            path = rb_str_encode_ospath(rb_get_path(argv[0]));
        }
        else {
            const char *dist = getenv("HOME");
            if (!dist) {
                dist = getenv("LOGDIR");
                if (!dist) rb_raise(rb_eArgError, "HOME/LOGDIR not set");
            }
            path = rb_str_new2(dist);
        }

        return chdir_path(path, true);
    }

children(dirpath) → array click to toggle source
children(dirpath, encoding: 'UTF-8') → array

Returns an array of the entry names in the directory at `dirpath` except for `'.'` and `'..'`; sets the given encoding onto each returned entry name:

    Dir.children('/example') # => ["config.h", "lib", "main.rb"]
    Dir.children('/example').first.encoding
    # => #<Encoding:UTF-8>
    Dir.children('/example', encoding: 'US-ASCII').first.encoding
    # => #<Encoding:US-ASCII>

See String Encoding.

Raises an exception if the directory does not exist.

    static VALUE
    dir_s_children(int argc, VALUE *argv, VALUE io)
    {
        VALUE dir;

        dir = dir_open_dir(argc, argv);
        return rb_ensure(dir_collect_children, dir, dir_close, dir);
    }

chroot(dirpath) → 0 click to toggle source

Changes the root directory of the calling process to that specified in `dirpath`. The new root directory is used for pathnames beginning with `'/'`. The root directory is inherited by all children of the calling process.

Only a privileged process may call `chroot`.

See Linux chroot.

    static VALUE
    dir_s_chroot(VALUE dir, VALUE path)
    {
        path = check_dirname(path);
        if (IO_WITHOUT_GVL_INT(nogvl_chroot, (void *)RSTRING_PTR(path)) == -1)
            rb_sys_fail_path(path);

        return INT2FIX(0);
    }

rmdir(dirpath) → 0 click to toggle source

Removes the directory at `dirpath` from the underlying file system:

    Dir.rmdir('foo') # => 0

Raises an exception if the directory is not empty.

    static VALUE
    dir_s_rmdir(VALUE obj, VALUE dir)
    {
        const char *p;
        int r;

        dir = check_dirname(dir);
        p = RSTRING_PTR(dir);
        r = IO_WITHOUT_GVL_INT(nogvl_rmdir, (void *)p);
        if (r < 0)
            rb_sys_fail_path(dir);

        return INT2FIX(0);
    }

each_child(dirpath) {|entry_name| ... } → nil click to toggle source
each_child(dirpath, encoding: 'UTF-8') {|entry_name| ... } → nil

Like `Dir.foreach`, except that entries `'.'` and `'..'` are not included.

    static VALUE
    dir_s_each_child(int argc, VALUE *argv, VALUE io)
    {
        VALUE dir;

        RETURN_ENUMERATOR(io, argc, argv);
        dir = dir_open_dir(argc, argv);
        rb_ensure(dir_each_child, dir, dir_close, dir);
        return Qnil;
    }

empty?(dirpath) → true or false click to toggle source

Returns whether `dirpath` specifies an empty directory:

    dirpath = '/tmp/foo'
    Dir.mkdir(dirpath)
    Dir.empty?(dirpath)            # => true
    Dir.empty?('/example')         # => false
    Dir.empty?('/example/main.rb') # => false

Raises an exception if `dirpath` does not specify a directory or file in the underlying file system.

    static VALUE
    rb_dir_s_empty_p(VALUE obj, VALUE dirname)
    {
        VALUE result, orig;
        const char *path;
        enum {false_on_notdir = 1};

        FilePathValue(dirname);
        orig = rb_str_dup_frozen(dirname);
        dirname = rb_str_encode_ospath(dirname);
        dirname = rb_str_dup_frozen(dirname);
        path = RSTRING_PTR(dirname);

    #if defined HAVE_GETATTRLIST && defined ATTR_DIR_ENTRYCOUNT
        {
            u_int32_t attrbuf[SIZEUP32(fsobj_tag_t)];
            struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_OBJTAG,};
            struct getattrlist_args args = GETATTRLIST_ARGS(&al, attrbuf, 0);
            if (gvl_getattrlist(&args, path) != 0)
                rb_sys_fail_path(orig);
            if (*(const fsobj_tag_t *)(attrbuf+1) == VT_HFS) {
                al.commonattr = 0;
                al.dirattr = ATTR_DIR_ENTRYCOUNT;
                if (gvl_getattrlist(&args, path) == 0) {
                    if (attrbuf[0] >= 2 * sizeof(u_int32_t))
                        return RBOOL(attrbuf[1] == 0);
                    if (false_on_notdir) return Qfalse;
                }
                rb_sys_fail_path(orig);
            }
        }
    #endif

        result = (VALUE)IO_WITHOUT_GVL(nogvl_dir_empty_p, (void *)path);
        if (FIXNUM_P(result)) {
            rb_syserr_fail_path((int)FIX2LONG(result), orig);
        }
        return result;
    }

entries(dirname, encoding: 'UTF-8') → array click to toggle source

Returns an array of the entry names in the directory at `dirpath`; sets the given encoding onto each returned entry name:

    Dir.entries('/example') # => ["config.h", "lib", "main.rb", "..", "."]
    Dir.entries('/example').first.encoding
    # => #<Encoding:UTF-8>
    Dir.entries('/example', encoding: 'US-ASCII').first.encoding
    # => #<Encoding:US-ASCII>

See String Encoding.

Raises an exception if the directory does not exist.

    static VALUE
    dir_entries(int argc, VALUE *argv, VALUE io)
    {
        VALUE dir;

        dir = dir_open_dir(argc, argv);
        return rb_ensure(dir_collect, dir, dir_close, dir);
    }

exist?(dirpath) → true or false click to toggle source

Returns whether `dirpath` is a directory in the underlying file system:

    Dir.exist?('/example')         # => true
    Dir.exist?('/nosuch')          # => false
    Dir.exist?('/example/main.rb') # => false

Same as `File.directory?`.

    VALUE
    rb_file_directory_p(void)
    {
    }

fchdir(fd) → 0 click to toggle source
fchdir(fd) { ... } → object

Changes the current working directory to the directory specified by the integer file descriptor `fd`.

When passing a file descriptor over a UNIX socket or to a child process, using `fchdir` instead of `chdir` avoids the time-of-check to time-of-use vulnerability

With no block, changes to the directory given by `fd`:

    Dir.chdir('/var/spool/mail')
    Dir.pwd # => "/var/spool/mail"
    dir  = Dir.new('/usr')
    fd = dir.fileno
    Dir.fchdir(fd)
    Dir.pwd # => "/usr"

With a block, temporarily changes the working directory:

- Calls the block with the argument.

- Changes to the given directory.

- Executes the block (yields no args).

- Restores the previous working directory.

- Returns the block’s return value.

Example:

    Dir.chdir('/var/spool/mail')
    Dir.pwd # => "/var/spool/mail"
    dir  = Dir.new('/tmp')
    fd = dir.fileno
    Dir.fchdir(fd) do
      Dir.pwd # => "/tmp"
    end
    Dir.pwd # => "/var/spool/mail"

This method uses the fchdir() function defined by POSIX 2008; the method is not implemented on non-POSIX platforms (raises `NotImplementedError`).

Raises an exception if the file descriptor is not valid.

In a multi-threaded program an error is raised if a thread attempts to open a `chdir` block while another thread has one open, or a call to `chdir` without a block occurs inside a block passed to `chdir` (even in the same thread).

    static VALUE
    dir_s_fchdir(VALUE klass, VALUE fd_value)
    {
        int fd = RB_NUM2INT(fd_value);

        if (chdir_alone_block_p()) {
            struct fchdir_data args;
            args.old_dir = dir_s_alloc(klass);
            dir_initialize(NULL, args.old_dir, rb_fstring_cstr("."), Qnil);
            args.fd = fd;
            args.done = FALSE;
            return rb_ensure(fchdir_yield, (VALUE)&args, fchdir_restore, (VALUE)&args);
        }
        else {
            int r = IO_WITHOUT_GVL_INT(nogvl_fchdir, &fd);
            if (r < 0)
                rb_sys_fail("fchdir");
        }

        return INT2FIX(0);
    }

for_fd(fd) → dir click to toggle source

Returns a new Dir object representing the directory specified by the given integer directory file descriptor `fd`:

    d0 = Dir.new('..')
    d1 = Dir.for_fd(d0.fileno)

Note that the returned `d1` does not have an associated path:

    d0.path # => '..'
    d1.path # => nil

This method uses the fdopendir() function defined by POSIX 2008; the method is not implemented on non-POSIX platforms (raises `NotImplementedError`).

    static VALUE
    dir_s_for_fd(VALUE klass, VALUE fd)
    {
        struct dir_data *dp;
        VALUE dir = TypedData_Make_Struct(klass, struct dir_data, &dir_data_type, dp);

        if (!(dp->dir = IO_WITHOUT_GVL(nogvl_fdopendir, (void *)(VALUE)NUM2INT(fd)))) {
            rb_sys_fail("fdopendir");
            UNREACHABLE_RETURN(Qnil);
        }

        RB_OBJ_WRITE(dir, &dp->path, Qnil);
        return dir;
    }

foreach(dirpath, encoding: 'UTF-8') {|entry_name| ... } → nil click to toggle source

Calls the block with each entry name in the directory at `dirpath`; sets the given encoding onto each passed `entry_name`:

    Dir.foreach('/example') {|entry_name| p entry_name }

Output:

    "config.h"
    "lib"
    "main.rb"
    ".."
    "."

Encoding:

    Dir.foreach('/example') {|entry_name| p entry_name.encoding; break }
    Dir.foreach('/example', encoding: 'US-ASCII') {|entry_name| p entry_name.encoding; break }

Output:

    #<Encoding:UTF-8>
    #<Encoding:US-ASCII>

See String Encoding.

Returns an enumerator if no block is given.

    static VALUE
    dir_foreach(int argc, VALUE *argv, VALUE io)
    {
        VALUE dir;

        RETURN_ENUMERATOR(io, argc, argv);
        dir = dir_open_dir(argc, argv);
        rb_ensure(dir_each, dir, dir_close, dir);
        return Qnil;
    }

pwd → string click to toggle source

Returns the path to the current working directory:

    Dir.chdir("/tmp") # => 0
    Dir.pwd           # => "/tmp"

    static VALUE
    dir_s_getwd(VALUE dir)
    {
        return rb_dir_getwd();
    }

glob(*patterns, flags: 0, base: nil, sort: true) → array click to toggle source
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):

    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:

- `'*'`: 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, 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):

    # 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.

    # File ruby_3_4_1/dir.rb, line 410
    def self.glob(pattern, _flags = 0, flags: _flags, base: nil, sort: true)
      Primitive.attr! :use_block
      Primitive.dir_s_glob(pattern, flags, base, sort)
    end

home(user_name = nil) → dirpath click to toggle source

Returns the home directory path of the user specified with `user_name` if it is not `nil`, or the current login user:

    Dir.home         # => "/home/me"
    Dir.home('root') # => "/root"

Raises `ArgumentError` if `user_name` is not a user name.

    static VALUE
    dir_s_home(int argc, VALUE *argv, VALUE obj)
    {
        VALUE user;
        const char *u = 0;

        rb_check_arity(argc, 0, 1);
        user = (argc > 0) ? argv[0] : Qnil;
        if (!NIL_P(user)) {
            StringValue(user);
            rb_must_asciicompat(user);
            u = StringValueCStr(user);
            if (*u) {
                return rb_home_dir_of(user, rb_str_new(0, 0));
            }
        }
        return rb_default_home_dir(rb_str_new(0, 0));

    }

mkdir(dirpath, permissions = 0775) → 0 click to toggle source

Creates a directory in the underlying file system at `dirpath` with the given `permissions`; returns zero:

    Dir.mkdir('foo')
    File.stat(Dir.new('foo')).mode.to_s(8)[1..4] # => "0755"
    Dir.mkdir('bar', 0644)
    File.stat(Dir.new('bar')).mode.to_s(8)[1..4] # => "0644"

See File Permissions. Note that argument `permissions` is ignored on Windows.

    static VALUE
    dir_s_mkdir(int argc, VALUE *argv, VALUE obj)
    {
        struct mkdir_arg m;
        VALUE path, vmode;
        int r;

        if (rb_scan_args(argc, argv, "11", &path, &vmode) == 2) {
            m.mode = NUM2MODET(vmode);
        }
        else {
            m.mode = 0777;
        }

        path = check_dirname(path);
        m.path = RSTRING_PTR(path);
        r = IO_WITHOUT_GVL_INT(nogvl_mkdir, &m);
        if (r < 0)
            rb_sys_fail_path(path);

        return INT2FIX(0);
    }

new(dirpath) → dir click to toggle source
new(dirpath, encoding: nil) → dir

Returns a new Dir object for the directory at `dirpath`:

    Dir.new('.') # => #<Dir:.>

The value given with optional keyword argument `encoding` specifies the encoding for the directory entry names; if `nil` (the default), the file system’s encoding is used:

    Dir.new('.').read.encoding                       # => #<Encoding:UTF-8>
    Dir.new('.', encoding: 'US-ASCII').read.encoding # => #<Encoding:US-ASCII>

    # File ruby_3_4_1/dir.rb, line 211
    def initialize(name, encoding: nil)
      Primitive.dir_initialize(name, encoding)
    end

open(dirpath) → dir click to toggle source
open(dirpath, encoding: nil) → dir
open(dirpath) {|dir| ... } → object
open(dirpath, encoding: nil) {|dir| ... } → object

Creates a new Dir object dir for the directory at `dirpath`.

With no block, the method equivalent to `Dir.new`(dirpath, encoding):

    Dir.open('.') # => #<Dir:.>

With a block given, the block is called with the created dir; on block exit dir is closed and the block’s value is returned:

    Dir.open('.') {|dir| dir.inspect } # => "#<Dir:.>"

The value given with optional keyword argument `encoding` specifies the encoding for the directory entry names; if `nil` (the default), the file system’s encoding is used:

    Dir.open('.').read.encoding                       # => #<Encoding:UTF-8>
    Dir.open('.', encoding: 'US-ASCII').read.encoding # => #<Encoding:US-ASCII>

    # File ruby_3_4_1/dir.rb, line 183
    def self.open(name, encoding: nil, &block)
      dir = Primitive.dir_s_open(name, encoding)
      if block
        begin
          yield dir
        ensure
          Primitive.dir_s_close(dir)
        end
      else
        dir
      end
    end

pwd → string click to toggle source

Returns the path to the current working directory:

    Dir.chdir("/tmp") # => 0
    Dir.pwd           # => "/tmp"

    static VALUE
    dir_s_getwd(VALUE dir)
    {
        return rb_dir_getwd();
    }

rmdir(dirpath) → 0 click to toggle source

Removes the directory at `dirpath` from the underlying file system:

    Dir.rmdir('foo') # => 0

Raises an exception if the directory is not empty.

    static VALUE
    dir_s_rmdir(VALUE obj, VALUE dir)
    {
        const char *p;
        int r;

        dir = check_dirname(dir);
        p = RSTRING_PTR(dir);
        r = IO_WITHOUT_GVL_INT(nogvl_rmdir, (void *)p);
        if (r < 0)
            rb_sys_fail_path(dir);

        return INT2FIX(0);
    }

rmdir(dirpath) → 0 click to toggle source

Removes the directory at `dirpath` from the underlying file system:

    Dir.rmdir('foo') # => 0

Raises an exception if the directory is not empty.

    static VALUE
    dir_s_rmdir(VALUE obj, VALUE dir)
    {
        const char *p;
        int r;

        dir = check_dirname(dir);
        p = RSTRING_PTR(dir);
        r = IO_WITHOUT_GVL_INT(nogvl_rmdir, (void *)p);
        if (r < 0)
            rb_sys_fail_path(dir);

        return INT2FIX(0);
    }

### Public Instance Methods

chdir → 0 click to toggle source
chdir { ... } → object

Changes the current working directory to `self`:

    Dir.pwd # => "/"
    dir = Dir.new('example')
    dir.chdir
    Dir.pwd # => "/example"

With a block, temporarily changes the working directory:

- Calls the block.

- Changes to the given directory.

- Executes the block (yields no args).

- Restores the previous working directory.

- Returns the block’s return value.

Uses `Dir.fchdir` if available, and `Dir.chdir` if not, see those methods for caveats.

    static VALUE
    dir_chdir(VALUE dir)
    {
    #if defined(HAVE_FCHDIR) && defined(HAVE_DIRFD) && HAVE_FCHDIR && HAVE_DIRFD
        return dir_s_fchdir(rb_cDir, dir_fileno(dir));
    #else
        return chdir_path(dir_get(dir)->path, false);
    #endif
    }

children → array click to toggle source

Returns an array of the entry names in `self` except for `'.'` and `'..'`:

    dir = Dir.new('/example')
    dir.children # => ["config.h", "lib", "main.rb"]

    static VALUE
    dir_collect_children(VALUE dir)
    {
        VALUE ary = rb_ary_new();
        dir_each_entry(dir, rb_ary_push, ary, TRUE);
        return ary;
    }

close → nil click to toggle source

Closes the stream in `self`, if it is open, and returns `nil`; ignored if `self` is already closed:

    dir = Dir.new('example')
    dir.read     # => "."
    dir.close     # => nil
    dir.close     # => nil
    dir.read # Raises IOError.

    static VALUE
    dir_close(VALUE dir)
    {
        struct dir_data *dirp;

        dirp = dir_get(dir);
        if (!dirp->dir) return Qnil;
        close_dir_data(dirp);

        return Qnil;
    }

each {|entry_name| ... } → self click to toggle source

Calls the block with each entry name in `self`:

    Dir.new('example').each {|entry_name| p entry_name }

Output:

    "."
    ".."
    "config.h"
    "lib"
    "main.rb"

With no block given, returns an `Enumerator`.

    static VALUE
    dir_each(VALUE dir)
    {
        RETURN_ENUMERATOR(dir, 0, 0);
        return dir_each_entry(dir, dir_yield, Qnil, FALSE);
    }

each_child {|entry_name| ... } → self click to toggle source

Calls the block with each entry name in `self` except `'.'` and `'..'`:

    dir = Dir.new('/example')
    dir.each_child {|entry_name| p entry_name }

Output:

    "config.h"
    "lib"
    "main.rb"

If no block is given, returns an enumerator.

    static VALUE
    dir_each_child_m(VALUE dir)
    {
        RETURN_ENUMERATOR(dir, 0, 0);
        return dir_each_entry(dir, dir_yield, Qnil, TRUE);
    }

fileno → integer click to toggle source

Returns the file descriptor used in dir.

    d = Dir.new('..')
    d.fileno # => 8

This method uses the dirfd() function defined by POSIX 2008; the method is not implemented on non-POSIX platforms (raises `NotImplementedError`).

    static VALUE
    dir_fileno(VALUE dir)
    {
        struct dir_data *dirp;
        int fd;

        GetDIR(dir, dirp);
        fd = dirfd(dirp->dir);
        if (fd == -1)
            rb_sys_fail("dirfd");
        return INT2NUM(fd);
    }

inspect → string click to toggle source

Returns a string description of `self`:

    Dir.new('example').inspect # => "#<Dir:example>"

    static VALUE
    dir_inspect(VALUE dir)
    {
        struct dir_data *dirp;

        TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dirp);
        if (!NIL_P(dirp->path)) {
            VALUE str = rb_str_new_cstr("#<");
            rb_str_append(str, rb_class_name(CLASS_OF(dir)));
            rb_str_cat2(str, ":");
            rb_str_append(str, dirp->path);
            rb_str_cat2(str, ">");
            return str;
        }
        return rb_funcallv(dir, idTo_s, 0, 0);
    }

path → string or nil click to toggle source

Returns the `dirpath` string that was used to create `self` (or `nil` if created by method `Dir.for_fd`):

    Dir.new('example').path # => "example"

    static VALUE
    dir_path(VALUE dir)
    {
        struct dir_data *dirp;

        TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dirp);
        if (NIL_P(dirp->path)) return Qnil;
        return rb_str_dup(dirp->path);
    }

Also aliased as: to_path
pos()

Returns the current position of `self`; see Dir As Stream-Like:

    dir = Dir.new('example')
    dir.tell  # => 0
    dir.read  # => "."
    dir.tell  # => 1

Alias for: tell
pos = position → integer click to toggle source

Sets the position in `self` and returns `position`. The value of `position` should have been returned from an earlier call to `tell`; if not, the return values from subsequent calls to `read` are unspecified.

See Dir As Stream-Like.

Examples:

    dir = Dir.new('example')
    dir.pos      # => 0
    dir.pos = 3  # => 3
    dir.pos      # => 3
    dir.pos = 30 # => 30
    dir.pos      # => 5

    static VALUE
    dir_set_pos(VALUE dir, VALUE pos)
    {
        dir_seek(dir, pos);
        return pos;
    }

read → string or nil click to toggle source

Reads and returns the next entry name from `self`; returns `nil` if at end-of-stream; see Dir As Stream-Like:

    dir = Dir.new('example')
    dir.read # => "."
    dir.read # => ".."
    dir.read # => "config.h"

    static VALUE
    dir_read(VALUE dir)
    {
        struct dir_data *dirp;
        struct dirent *dp;

        GetDIR(dir, dirp);
        rb_errno_set(0);
        if ((dp = READDIR(dirp->dir, dirp->enc)) != NULL) {
            return rb_external_str_new_with_enc(dp->d_name, NAMLEN(dp), dirp->enc);
        }
        else {
            int e = errno;
            if (e != 0) rb_syserr_fail(e, 0);
            return Qnil;            /* end of stream */
        }
    }

rewind → self click to toggle source

Sets the position in `self` to zero; see Dir As Stream-Like:

    dir = Dir.new('example')
    dir.read    # => "."
    dir.read    # => ".."
    dir.pos     # => 2
    dir.rewind  # => #<Dir:example>
    dir.pos     # => 0

    static VALUE
    dir_rewind(VALUE dir)
    {
        struct dir_data *dirp;

        GetDIR(dir, dirp);
        rewinddir(dirp->dir);
        return dir;
    }

seek(position) → self click to toggle source

Sets the position in `self` and returns `self`. The value of `position` should have been returned from an earlier call to `tell`; if not, the return values from subsequent calls to `read` are unspecified.

See Dir As Stream-Like.

Examples:

    dir = Dir.new('example')
    dir.pos      # => 0
    dir.seek(3)  # => #<Dir:example>
    dir.pos      # => 3
    dir.seek(30) # => #<Dir:example>
    dir.pos      # => 5

    static VALUE
    dir_seek(VALUE dir, VALUE pos)
    {
        struct dir_data *dirp;
        long p = NUM2LONG(pos);

        GetDIR(dir, dirp);
        seekdir(dirp->dir, p);
        return dir;
    }

tell → integer click to toggle source

Returns the current position of `self`; see Dir As Stream-Like:

    dir = Dir.new('example')
    dir.tell  # => 0
    dir.read  # => "."
    dir.tell  # => 1

    static VALUE
    dir_tell(VALUE dir)
    {
        struct dir_data *dirp;
        long pos;

        GetDIR(dir, dirp);
        if((pos = telldir(dirp->dir)) < 0)
            rb_sys_fail("telldir");
        return rb_int2inum(pos);
    }

Also aliased as: pos
to_path()

Returns the `dirpath` string that was used to create `self` (or `nil` if created by method `Dir.for_fd`):

    Dir.new('example').path # => "example"

Alias for: path