Spec-Zone.ru › Ruby 4.0

класс Dir

Родительский класс:
Object
Подключённые модули:
Enumerable

Объект класса Dir представляет каталог в базовой файловой системе.

В основном он состоит из:

  • Строкового пути, задаваемого при создании объекта и указывающего на каталог в базовой файловой системе; метод path возвращает этот путь.

  • Набора строковых имён записей, каждая из которых является именем каталога или файла в базовой файловой системе; имена записей можно получить в форме, подобной массиву, или в форме, подобной потоку.

Об этом примере

В некоторых примерах на этой странице используется простое дерево файлов:

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

В других используется дерево файлов самого проекта Ruby.

Dir в форме, подобной массиву

Объект Dir в некоторых отношениях похож на массив:

  • У него есть методы экземпляра children, each и each_child.

  • Он подключает модуль Enumerable.

Dir в форме, подобной потоку

Объект Dir в некоторых отношениях похож на поток.

Изначально поток открыт для чтения, но его можно закрыть вручную (с помощью метода close); также он будет закрыт при выходе из блока, если создан методом Dir.open, вызванным с блоком. Закрытым потоком нельзя управлять, и его нельзя открыть повторно.

Поток имеет позицию, то есть индекс записи в каталоге:

  • Начальная позиция равна нулю (перед первой записью).

  • Метод tell (с псевдонимом pos) возвращает позицию.

  • Метод pos= задаёт позицию (но игнорирует значение за пределами потока) и возвращает позицию.

  • Метод seek аналогичен методу pos=, но возвращает self (что удобно для цепочек вызовов).

  • Метод read, если поток не достиг конца, считывает следующую запись и увеличивает позицию; если поток достиг конца, позиция не увеличивается.

  • Метод rewind устанавливает позицию в ноль.

Примеры (с использованием простого дерева файлов):

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.

Что здесь есть

Сначала рассмотрим, что находится в других местах. Класс Dir:

  • Наследуется от класса Object.

  • Подключает модуль Enumerable, предоставляющий десятки дополнительных методов.

Класс Dir предоставляет методы для:

  • Чтения

  • Настройки

  • Запросов

  • Итерирования

  • Прочего

Чтение

  • close: Закрывает поток каталога для self.

  • pos=: Устанавливает позицию в потоке каталога для self.

  • read: Считывает и возвращает следующую запись в потоке каталога для self.

  • rewind: Устанавливает позицию в потоке каталога для self на первую запись.

  • seek: Устанавливает позицию в потоке каталога для self на запись с заданным смещением.

Настройка

  • ::chdir: Изменяет рабочий каталог текущего процесса на указанный каталог.

  • ::chroot: Изменяет корень файловой системы для текущего процесса на указанный каталог.

Запросы

  • ::[]: То же, что и ::glob, но без возможности передать флаги.

  • ::children: Возвращает массив имён дочерних элементов (файлов и каталогов) указанного каталога, не включая . или ...

  • ::empty?: Возвращает признак того, что указанный путь является пустым каталогом.

  • ::entries: Возвращает массив имён дочерних элементов (файлов и каталогов) указанного каталога, включая . и ...

  • ::exist?: Возвращает признак того, что указанный путь является каталогом.

  • ::getwd (с псевдонимом pwd): Возвращает путь к текущему рабочему каталогу.

  • ::glob: Возвращает массив путей к файлам, соответствующих заданному шаблону и флагам.

  • ::home: Возвращает путь к домашнему каталогу указанного или текущего пользователя.

  • children: Возвращает массив имён дочерних элементов (файлов и каталогов) self, не включая . или ...

  • fileno: Возвращает целочисленный дескриптор файла для self.

  • path (с псевдонимом to_path): Возвращает путь, использованный для создания self.

  • tell (с псевдонимом pos): Возвращает целочисленную позицию в потоке каталога для self.

Итерирование

  • ::each_child: Вызывает переданный блок для каждой записи в указанном каталоге, не включая . или ...

  • ::foreach: Вызывает переданный блок для каждой записи в указанном каталоге, включая . и ...

  • each: Вызывает переданный блок для каждой записи в self, включая . и ...

  • each_child: Вызывает переданный блок для каждой записи в self, не включая . или ...

Прочее

  • ::mkdir: Создаёт каталог по указанному пути с необязательным заданием прав доступа.

  • ::new: Возвращает новый объект Dir для указанного пути с необязательной кодировкой.

  • ::open: То же, что и ::new, но если передан блок, передаёт ему объект Dir и закрывает его при выходе из блока.

  • ::unlink (с псевдонимами ::delete и ::rmdir): Удаляет указанный каталог.

  • inspect: Возвращает строковое описание self.

Публичные методы класса

Dir[*patterns, base: nil, sort: true] → array Показать исходный код
# File dir.rb, line 222
def self.[](*args, base: nil, sort: true)
  Primitive.dir_s_aref(args, base, sort)
end

Вызывает Dir.glob с аргументом patterns и значениями ключевых аргументов base и sort; возвращает массив выбранных имён записей.

chdir(new_dirpath) → 0 Показать исходный код
chdir → 0
chdir(new_dirpath) {|new_dirpath| ... } → object
chdir {|cur_dirpath| ... } → object
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);
}

Изменяет текущий рабочий каталог.

С аргументом new_dirpath и без блока переходит в указанный dirpath:

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

Без аргумента и без блока:

  • Переходит в каталог, указанный значением переменной окружения HOME, если она задана.

  • В противном случае переходит в каталог, указанный значением переменной окружения LOGDIR, если она задана.

  • В противном случае ничего не меняет.

С аргументом new_dirpath и блоком временно изменяет рабочий каталог:

  • Вызывает блок с аргументом.

  • Переходит в указанный каталог.

  • Выполняет блок (передавая ему новый путь).

  • Восстанавливает предыдущий рабочий каталог.

  • Возвращает значение, возвращённое блоком.

Пример:

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

Без аргумента и с блоком вызывает блок, передавая ему текущий рабочий каталог (строку), и возвращает значение, возвращённое блоком.

Вызовы Dir.chdir с блоками можно вкладывать друг в друга:

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"

В многопоточной программе возникает ошибка, если поток пытается открыть блок chdir, когда другой поток уже открыл такой блок, или если вызов chdir без блока выполняется внутри блока, переданного в chdir (даже в том же потоке).

Вызывает исключение, если целевой каталог не существует.

children(dirpath) → array Показать исходный код
children(dirpath, encoding: 'UTF-8') → array
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);
}

Возвращает массив имён записей каталога по пути dirpath, исключая '.' и '..'; задаёт указанную кодировку для каждого возвращённого имени записи:

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>

См. Кодировка строк.

Вызывает исключение, если каталог не существует.

chroot(dirpath) → 0 Показать исходный код
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);
}

Изменяет корневой каталог вызывающего процесса на каталог, указанный в dirpath. Новый корневой каталог используется для путей, начинающихся с '/'. Корневой каталог наследуется всеми дочерними процессами вызывающего процесса.

Вызывать chroot может только привилегированный процесс.

См. Linux chroot.

rmdir(dirpath) → 0 Показать исходный код
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);
}

Удаляет каталог по пути dirpath из базовой файловой системы:

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

Вызывает исключение, если каталог не пуст.

each_child(dirpath) {|entry_name| ... } → nil Показать исходный код
each_child(dirpath, encoding: 'UTF-8') {|entry_name| ... } → nil
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;
}

Аналогичен Dir.foreach, за исключением того, что записи '.' и '..' не включаются.

empty?(dirpath) → true or false Показать исходный код
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;
}

Возвращает значение, указывающее, задаёт ли dirpath пустой каталог:

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

Вызывает исключение, если dirpath не задаёт каталог или файл в базовой файловой системе.

entries(dirname, encoding: 'UTF-8') → array Показать исходный код
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);
}

Возвращает массив имён записей каталога по пути dirpath; задаёт указанную кодировку для каждого возвращённого имени записи:

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>

См. Кодировка строк.

Вызывает исключение, если каталог не существует.

exist?(dirpath) → true or false Показать исходный код
VALUE
rb_file_directory_p(void)
{
}

Возвращает значение, указывающее, является ли dirpath каталогом в базовой файловой системе:

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

То же, что и File.directory?.

fchdir(fd) → 0 Показать исходный код
fchdir(fd) { ... } → object
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);
}

Изменяет текущий рабочий каталог на каталог, указанный целочисленным дескриптором файла fd.

При передаче дескриптора файла через сокет UNIX или дочернему процессу использование fchdir вместо chdir позволяет избежать уязвимости, связанной с разницей во времени между проверкой и использованием.

Без блока переходит в каталог, заданный fd:

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

С блоком временно изменяет рабочий каталог:

  • Вызывает блок с аргументом.

  • Переходит в указанный каталог.

  • Выполняет блок (не передавая аргументов).

  • Восстанавливает предыдущий рабочий каталог.

  • Возвращает значение, возвращённое блоком.

Пример:

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"

Этот метод использует функцию fchdir(), определённую стандартом POSIX 2008; метод не реализован на платформах, не поддерживающих POSIX (вызывает NotImplementedError).

Вызывает исключение, если дескриптор файла недействителен.

В многопоточной программе возникает ошибка, если поток пытается открыть блок chdir, когда другой поток уже открыл такой блок, или если вызов chdir без блока выполняется внутри блока, переданного в chdir (даже в том же потоке).

for_fd(fd) → dir Показать исходный код
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;
}

Возвращает новый объект Dir, представляющий каталог, указанный заданным целочисленным дескриптором файла каталога fd:

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

Обратите внимание, что у возвращённого d1 нет связанного пути:

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

Этот метод использует функцию fdopendir(), определённую стандартом POSIX 2008; метод не реализован на платформах, не поддерживающих POSIX (вызывает NotImplementedError).

foreach(dirpath, encoding: 'UTF-8') {|entry_name| ... } → nil Показать исходный код
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;
}

Вызывает блок для каждого имени записи в каталоге по пути dirpath; задаёт указанную кодировку для каждой передаваемой entry_name:

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

Вывод:

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

Кодировка:

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

Вывод:

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

См. Кодировка строк.

Если блок не задан, возвращает перечислитель.

pwd → string Показать исходный код
static VALUE
dir_s_getwd(VALUE dir)
{
    return rb_dir_getwd();
}

Возвращает путь к текущему рабочему каталогу:

Dir.chdir("/tmp") # => 0
Dir.pwd           # => "/tmp"
glob(patterns, flags: 0, base: nil, sort: true) → array Показать исходный код
glob(patterns, flags: 0, base: nil, sort: true) {|entry_name| ... } → nil
# File 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

Формирует массив entry_names из имён записей, выбранных аргументами.

Аргумент patterns — это строковый шаблон или массив строковых шаблонов; обратите внимание, что это не регулярные выражения; см. ниже.

Примечания к следующим примерам:

  • '*' — это шаблон, соответствующий любому имени записи, кроме начинающихся с '.'.

  • Для сокращения возвращаемых массивов, которые иначе были бы очень большими, используется метод Array#take.

Без блока возвращает массив entry_names; пример (с использованием простого дерева файлов):

Dir.glob('*') # => ["config.h", "lib", "main.rb"]

С блоком вызывает блок для каждого из entry_names и возвращает nil:

Dir.glob('*') {|entry_name| puts entry_name } # => nil

Вывод:

config.h
lib
main.rb

Если указан необязательный ключевой аргумент flags, его значение изменяет сопоставление; см. ниже.

Если указан необязательный ключевой аргумент base, его значение задаёт базовый каталог. Каждый строковый шаблон задаёт записи относительно базового каталога; по умолчанию используется '.'. Базовый каталог не добавляется к именам записей в результате:

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"]

Если указан необязательный ключевой аргумент sort, его значение определяет, нужно ли сортировать массив; по умолчанию используется true. Передача значения false этому аргументу отключает сортировку (хотя базовая файловая система могла уже отсортировать массив).

Шаблоны

Каждый строковый шаблон раскрывается с учётом определённых метасимволов; в примерах ниже используется дерево файлов Ruby:

  • '*': соответствует любой подстроке в имени записи, подобно регулярному выражению /.*/mx; сопоставление может быть ограничено другими значениями в строковых шаблонах:

    • '*' соответствует всем именам записей:

      Dir.glob('*').take(3)  # => ["BSDL", "CONTRIBUTING.md", "COPYING"]
      
    • 'c*' соответствует именам записей, начинающимся с 'c':

      Dir.glob('c*').take(3) # => ["CONTRIBUTING.md", "COPYING", "COPYING.ja"]
      
    • '*c' соответствует именам записей, заканчивающимся на 'c':

      Dir.glob('*c').take(3) # => ["addr2line.c", "array.c", "ast.c"]
      
    • '*c*' соответствует именам записей, содержащим 'c', в том числе в начале или конце:

      Dir.glob('*c*').take(3) # => ["CONTRIBUTING.md", "COPYING", "COPYING.ja"]
      

    Не соответствует скрытым именам записей в Unix-подобных системах («файлам с точкой»). Чтобы включить их в список соответствующих имён, используйте флаг IO::FNM_DOTMATCH или что-нибудь вроде '{*,.*}'.

  • '**': рекурсивно сопоставляет имена записей, если за ним следует символ косой черты '/':

    Dir.glob('**/').take(3) # => ["basictest/", "benchmark/", "benchmark/gc/"]
    

    Если строковый шаблон содержит другие символы или после него не следует символ косой черты, он эквивалентен '*'.

  • '?' соответствует любому одиночному символу; по смыслу подобен регулярному выражению /./:

    Dir.glob('io.?') # => ["io.c"]
    
  • '[set]': соответствует любому одному символу из строки set; работает как класс символов регулярного выражения, включая отрицание множества ('[^a-z]'):

    Dir.glob('*.[a-z][a-z]').take(3)
    # => ["CONTRIBUTING.md", "COPYING.ja", "KNOWNBUGS.rb"]
    
  • '{abc,xyz}': соответствует строке abc или строке xyz; работает как альтернатива регулярного выражения:

    Dir.glob('{LEGAL,BSDL}') # => ["LEGAL", "BSDL"]
    

    Можно указать более двух вариантов.

  • \: экранирует следующий метасимвол.

    Обратите внимание, что в Windows символ обратной косой черты нельзя использовать в строковом шаблоне: Dir['c:\foo*'] не сработает, используйте вместо него Dir['c:/foo*'].

Другие примеры (с использованием простого дерева файлов):

# 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 (по умолчанию равен нулю — флаги не заданы), его значение должно быть побитовым ИЛИ одной или нескольких констант, определённых в модуле File::Constants.

Пример:

flags = File::FNM_EXTGLOB | File::FNM_DOTMATCH

Указание флагов может расширить, ограничить или иным образом изменить сопоставление.

Флаги для этого метода (другие константы из File::Constants не применяются):

  • File::FNM_DOTMATCH: указывает, что при сопоставлении следует учитывать имена записей, начинающиеся с '.':

    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: включает расширение шаблона '{a,b}', соответствующее шаблону a и шаблону b; работает как объединение регулярных выражений (например, '(?:a|b)'):

    pattern = '{LEGAL,BSDL}'
    Dir.glob(pattern)      # => ["LEGAL", "BSDL"]
    
  • File::FNM_NOESCAPE: указывает, что экранирование с помощью символа обратной косой черты '\' отключено; этот символ не является символом экранирования.

  • File::FNM_PATHNAME: указывает, что метасимволы '*' и '?' не соответствуют разделителям каталогов.

  • File::FNM_SHORTNAME: указывает, что шаблоны могут соответствовать коротким именам, если они существуют; только для Windows.

home(user_name = nil) → dirpath Показать исходный код
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));

}

Возвращает путь к домашнему каталогу пользователя, указанного в user_name, если он не равен nil, или текущего пользователя системы:

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

Вызывает ArgumentError, если user_name не является именем пользователя.

mkdir(dirpath, permissions = 0775) → 0 Показать исходный код
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);
}

Создаёт каталог в базовой файловой системе по пути dirpath с заданными permissions; возвращает ноль:

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"

См. Права доступа к файлам. Обратите внимание, что аргумент permissions игнорируется в Windows.

mktmpdir (prefix_suffix=nil, *rest, **options) { |dup| ... } Показать исходный код
# File lib/tmpdir.rb, line 97
def self.mktmpdir(prefix_suffix=nil, *rest, **options, &block)
  base = nil
  path = Tmpname.create(prefix_suffix || "d", *rest, **options) {|path, _, _, d|
    base = d
    mkdir(path, 0700)
  }
  if block
    begin
      yield path.dup
    ensure
      unless base
        base = File.dirname(path)
        stat = File.stat(base)
        if stat.world_writable? and !stat.sticky?
          raise ArgumentError, "parent directory is world writable but not sticky: #{base}"
        end
      end
      FileUtils.remove_entry path
    end
  else
    path
  end
end

Dir.mktmpdir создаёт временный каталог.

require 'tmpdir'
Dir.mktmpdir {|dir|
  # use the directory
}

Каталог создаётся с правами доступа 0700. Приложению не следует изменять права доступа так, чтобы временный каталог был доступен другим пользователям.

Префикс и суффикс имени каталога задаются необязательным первым аргументом prefix_suffix.

  • Если он не задан или равен nil, используется префикс «d» и суффикс не используется.

  • Если это строка, она используется как префикс, суффикс не используется.

  • Если это массив, первый элемент используется как префикс, а второй — как суффикс.

Dir.mktmpdir {|dir| dir is ".../d..." }
Dir.mktmpdir("foo") {|dir| dir is ".../foo..." }
Dir.mktmpdir(["foo", "bar"]) {|dir| dir is ".../foo...bar" }

Каталог создаётся в Dir.tmpdir или во втором необязательном аргументе tmpdir, если задано ненулевое значение.

Dir.mktmpdir {|dir| dir is "#{Dir.tmpdir}/d..." }
Dir.mktmpdir(nil, "/var/tmp") {|dir| dir is "/var/tmp/d..." }

Если задан блок, ему передаётся путь к каталогу. Каталог и его содержимое удаляются с помощью FileUtils.remove_entry до того, как Dir.mktmpdir вернёт управление. Возвращается значение блока.

Dir.mktmpdir {|dir|
  # use the directory...
  open("#{dir}/foo", "w") { something using the file }
}

Если блок не задан, возвращается путь к каталогу. В этом случае Dir.mktmpdir не удаляет каталог.

dir = Dir.mktmpdir
begin
  # use the directory...
  open("#{dir}/foo", "w") { something using the file }
ensure
  # remove the directory.
  FileUtils.remove_entry dir
end
new(dirpath) → dir Показать исходный код
new(dirpath, encoding: nil) → dir
# File dir.rb, line 211
def initialize(name, encoding: nil)
  Primitive.dir_initialize(name, encoding)
end

Возвращает новый объект Dir для каталога по пути dirpath:

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

Значение необязательного ключевого аргумента encoding задаёт кодировку имён записей каталога; если значение равно nil (по умолчанию), используется кодировка файловой системы:

Dir.new('.').read.encoding                       # => #<Encoding:UTF-8>
Dir.new('.', encoding: Encoding::US_ASCI).read.encoding # => #<Encoding:US-ASCII>
open(dirpath) → dir Показать исходный код
open(dirpath, encoding: nil) → dir
open(dirpath) {|dir| ... } → object
open(dirpath, encoding: nil) {|dir| ... } → object
# File 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

Создаёт новый объект Dir dir для каталога по пути dirpath.

Без блока метод эквивалентен Dir.new(dirpath, encoding):

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

Если задан блок, он вызывается с созданным объектом dir; при выходе из блока dir закрывается, а возвращается значение блока:

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

Значение необязательного ключевого аргумента encoding задаёт кодировку имён записей каталога; если значение равно nil (по умолчанию), используется кодировка файловой системы:

Dir.open('.').read.encoding                       # => #<Encoding:UTF-8>
Dir.open('.', encoding: Encoding::US_ASCII).read.encoding # => #<Encoding:US-ASCII>
pwd → string Показать исходный код
static VALUE
dir_s_getwd(VALUE dir)
{
    return rb_dir_getwd();
}

Возвращает путь к текущему рабочему каталогу:

Dir.chdir("/tmp") # => 0
Dir.pwd           # => "/tmp"
rmdir(dirpath) → 0 Показать исходный код
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);
}

Удаляет каталог по пути dirpath из базовой файловой системы:

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

Вызывает исключение, если каталог не пуст.

tmpdir () Показать исходный код
# File lib/tmpdir.rb, line 25
def self.tmpdir
  Tmpname::TMPDIR_CANDIDATES.find do |name, dir|
    unless dir
      next if !(dir = ENV[name] rescue next) or dir.empty?
    end
    dir = File.expand_path(dir)
    stat = File.stat(dir) rescue next
    case
    when !stat.directory?
      warn "#{name} is not a directory: #{dir}"
    when !File.writable?(dir)
      # We call File.writable?, not stat.writable?, because you can't tell if a dir is actually
      # writable just from stat; OS mechanisms other than user/group/world bits can affect this.
      warn "#{name} is not writable: #{dir}"
    when stat.world_writable? && !stat.sticky?
      warn "#{name} is world-writable: #{dir}"
    else
      break dir
    end
  end or raise ArgumentError, "could not find a temporary directory"
end

Возвращает путь к временному каталогу операционной системы.

require 'tmpdir'
Dir.tmpdir # => "/tmp"
rmdir(dirpath) → 0 Показать исходный код
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);
}

Удаляет каталог по пути dirpath из базовой файловой системы:

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

Вызывает исключение, если каталог не пуст.

Открытые методы экземпляра

chdir → 0 Показать исходный код
chdir { ... } → object
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
}

Изменяет текущий рабочий каталог на self:

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

При наличии блока временно изменяет рабочий каталог:

  • Вызывает блок.

  • Переходит в указанный каталог.

  • Выполняет блок (без передачи аргументов).

  • Восстанавливает предыдущий рабочий каталог.

  • Возвращает значение, возвращённое блоком.

Использует Dir.fchdir, если этот метод доступен, и Dir.chdir в противном случае; ограничения описаны в документации этих методов.

children → array Показать исходный код
static VALUE
dir_collect_children(VALUE dir)
{
    VALUE ary = rb_ary_new();
    dir_each_entry(dir, rb_ary_push, ary, TRUE);
    return ary;
}

Возвращает массив имён записей в self, кроме '.' и '..':

dir = Dir.new('/example')
dir.children # => ["config.h", "lib", "main.rb"]
close → nil Показать исходный код
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;
}

Закрывает поток в self, если он открыт, и возвращает nil; если self уже закрыт, ничего не делает:

dir = Dir.new('example')
dir.read     # => "."
dir.close     # => nil
dir.close     # => nil
dir.read # Raises IOError.
each {|entry_name| ... } → self Показать исходный код
static VALUE
dir_each(VALUE dir)
{
    RETURN_ENUMERATOR(dir, 0, 0);
    return dir_each_entry(dir, dir_yield, Qnil, FALSE);
}

Вызывает блок для каждого имени записи в self:

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

Вывод:

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

Если блок не задан, возвращает Enumerator.

each_child {|entry_name| ... } → self Показать исходный код
static VALUE
dir_each_child_m(VALUE dir)
{
    RETURN_ENUMERATOR(dir, 0, 0);
    return dir_each_entry(dir, dir_yield, Qnil, TRUE);
}

Вызывает блок для каждого имени записи в self, кроме '.' и '..':

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

Вывод:

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

Если блок не задан, возвращает перечислитель.

fileno → integer Показать исходный код
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);
}

Возвращает файловый дескриптор, используемый в dir.

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

Этот метод использует функцию dirfd(), определённую стандартом POSIX 2008; метод не реализован на платформах, отличных от POSIX (вызывает исключение NotImplementedError).

inspect → string Показать исходный код
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);
}

Возвращает строковое описание self:

Dir.new('example').inspect # => "#<Dir:example>"
path → string or nil Показать исходный код
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);
}

Возвращает строку dirpath, использованную для создания self (или nil, если объект создан методом Dir.for_fd):

Dir.new('example').path # => "example"
Также имеет псевдоним: to_path
pos
Псевдоним для: tell
pos = position → integer Показать исходный код
static VALUE
dir_set_pos(VALUE dir, VALUE pos)
{
    dir_seek(dir, pos);
    return pos;
}

Устанавливает позицию в self и возвращает position. Значение position должно быть возвращено при предыдущем вызове tell; в противном случае возвращаемые значения последующих вызовов read не определены.

См. Каталог как поток.

Примеры:

dir = Dir.new('example')
dir.pos      # => 0
dir.pos = 3  # => 3
dir.pos      # => 3
dir.pos = 30 # => 30
dir.pos      # => 5
read → string or nil Показать исходный код
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 */
    }
}

Читает и возвращает имя следующей записи из self; возвращает nil при достижении конца потока; см. Каталог как поток:

dir = Dir.new('example')
dir.read # => "."
dir.read # => ".."
dir.read # => "config.h"
rewind → self Показать исходный код
static VALUE
dir_rewind(VALUE dir)
{
    struct dir_data *dirp;

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

Устанавливает позицию в self на ноль; см. Каталог как поток:

dir = Dir.new('example')
dir.read    # => "."
dir.read    # => ".."
dir.pos     # => 2
dir.rewind  # => #<Dir:example>
dir.pos     # => 0
seek(position) → self Показать исходный код
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;
}

Устанавливает позицию в self и возвращает self. Значение position должно быть возвращено при предыдущем вызове tell; в противном случае возвращаемые значения последующих вызовов read не определены.

См. Каталог как поток.

Примеры:

dir = Dir.new('example')
dir.pos      # => 0
dir.seek(3)  # => #<Dir:example>
dir.pos      # => 3
dir.seek(30) # => #<Dir:example>
dir.pos      # => 5
tell → integer Показать исходный код
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);
}

Возвращает текущую позицию self; см. Каталог как поток:

dir = Dir.new('example')
dir.tell  # => 0
dir.read  # => "."
dir.tell  # => 1
Также имеет псевдоним: pos
to_path
Псевдоним для: path

Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API