класс Dir
Объекты класса Dir являются потоками каталогов, представляющими каталоги в файловой системе. Они предоставляют различные способы перечисления каталогов и их содержимого. См. также File.
Каталог, используемый в этих примерах, содержит две обычные файлы (config.h и main.rb), родительский каталог (..), и сам каталог (.).
Методы публичного класса
static VALUE
dir_s_aref(int argc, VALUE *argv, VALUE obj)
{
if (argc == 1) {
return rb_push_glob(argv[0], 0);
}
return dir_globs(argc, argv, 0);
} Эквивалентно вызову Dir.glob([string,...],0).
static VALUE
dir_s_chdir(int argc, VALUE *argv, VALUE obj)
{
VALUE path = Qnil;
rb_secure(2);
if (rb_scan_args(argc, argv, "01", &path) == 1) {
FilePathValue(path);
path = rb_str_encode_ospath(path);
}
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);
}
if (chdir_blocking > 0) {
if (!rb_block_given_p() || rb_thread_current() != chdir_thread)
rb_warn("conflicting chdir during another chdir block");
}
if (rb_block_given_p()) {
struct chdir_data args;
args.old_path = rb_str_encode_ospath(rb_dir_getwd());
args.new_path = path;
args.done = FALSE;
return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args);
}
dir_chdir(path);
return INT2FIX(0);
} Изменяет текущий рабочий каталог процесса на заданную строку. При вызове без аргумента, изменяет каталог на значение переменной окружения HOME, или LOGDIR. SystemCallError (вероятно, Errno::ENOENT) если целевой каталог не существует.
Если блок указан, он получает имя нового текущего каталога, и блок выполняется с ним как текущим каталогом. Исходный рабочий каталог восстанавливается при выходе из блока. Значение возвращаемое chdir – это значение блока. chdir блоки могут быть вложены, но в многопоточной программе будет возбуждено исключение, если поток попытается открыть chdir блок, в то время как другой поток имеет его открытым.
Dir.chdir("/var/spool/mail")
puts Dir.pwd
Dir.chdir("/tmp") do
puts Dir.pwd
Dir.chdir("/usr") do
puts Dir.pwd
end
puts Dir.pwd
end
puts Dir.pwd
выводит:
/var/spool/mail /tmp /usr /tmp /var/spool/mail
static VALUE
dir_s_chroot(VALUE dir, VALUE path)
{
check_dirname(&path);
if (chroot(RSTRING_PTR(path)) == -1)
rb_sys_fail_path(path);
return INT2FIX(0);
} Изменяет представление корневой директории файловой системы в этом процессе. Только привилегированный процесс может сделать этот вызов. Недоступно на всех платформах. На системах Unix, см. chroot(2) для получения дополнительной информации.
static VALUE
dir_s_rmdir(VALUE obj, VALUE dir)
{
check_dirname(&dir);
if (rmdir(RSTRING_PTR(dir)) < 0)
rb_sys_fail_path(dir);
return INT2FIX(0);
} Удаляет указанный каталог. Вызывает подкласс SystemCallError если каталог не пуст.
static VALUE
dir_entries(int argc, VALUE *argv, VALUE io)
{
VALUE dir;
dir = dir_open_dir(argc, argv);
return rb_ensure(rb_Array, dir, dir_close, dir);
} Возвращает массив, содержащий все имена файлов в заданном каталоге. Вызовет SystemCallError если указанный каталог не существует.
Необязательный аргумент enc указывает кодировку каталога. Если не указано, используется кодировка файловой системы.
Dir.entries("testdir") #=> [".", "..", "config.h", "main.rb"]
VALUE
rb_file_directory_p(void)
{
} Возвращает true если указанный файл является каталогом, false в противном случае.
static VALUE
rb_dir_exists_p(VALUE obj, VALUE fname)
{
rb_warning("Dir.exists? is a deprecated name, use Dir.exist? instead");
return rb_file_directory_p(obj, fname);
} Метод устарел. Не использовать.
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;
} Вызывает блок один раз для каждой записи в указанном каталоге, передавая имя файла каждой записи в качестве параметра блоку.
Если блок не указан, возвращается перечислитель вместо этого.
Dir.foreach("testdir") {|x| puts "Got #{x}" }
выводит:
Got . Got .. Got config.h Got main.rb
static VALUE
dir_s_getwd(VALUE dir)
{
return rb_dir_getwd();
} Возвращает путь к текущему рабочему каталогу этого процесса в виде строки.
Dir.chdir("/tmp") #=> 0
Dir.getwd #=> "/tmp"
Dir.pwd #=> "/tmp"
static VALUE
dir_s_glob(int argc, VALUE *argv, VALUE obj)
{
VALUE str, rflags, ary;
int flags;
if (rb_scan_args(argc, argv, "11", &str, &rflags) == 2)
flags = NUM2INT(rflags);
else
flags = 0;
ary = rb_check_array_type(str);
if (NIL_P(ary)) {
ary = rb_push_glob(str, flags);
}
else {
VALUE v = ary;
ary = dir_globs(RARRAY_LEN(v), RARRAY_CONST_PTR(v), flags);
RB_GC_GUARD(v);
}
if (rb_block_given_p()) {
rb_ary_each(ary);
return Qnil;
}
return ary;
} Расширяет pattern, что является массивом шаблонов или строкой шаблона, и возвращает результаты как matches или в качестве аргументов, переданных в блок.
Обратите внимание, что этот шаблон не является регулярным выражением, он ближе к оболочке glob. Смотрите File.fnmatch для значения параметра flags. Обратите внимание, что чувствительность к регистру зависит от вашей системы (поэтому File::FNM_CASEFOLD игнорируется), как и порядок, в котором возвращаются результаты.
-
* -
Соответствует любому файлу. Может быть ограничен другими значениями в glob. Эквивалентно
/ .* /xв регулярных выражениях.-
* -
Соответствует всем файлам
-
c* -
Соответствует всем файлам, начинающимся с
c -
*c -
Соответствует всем файлам, оканчивающимся на
c -
*c* -
Соответствует всем файлам, содержащим
c(включая начало и конец).
Обратите внимание, что это не будет соответствовать скрытым файлам (файлам с точкой) в стиле Unix. Для включения этих результатов в совпадения, необходимо использовать флаг File::FNM_DOTMATCH или что-то вроде
"{*,.*}". -
-
** -
Соответствует каталогам рекурсивно.
-
? -
Соответствует одному символу. Эквивалентно
/.{1}/в регулярных выражениях. -
[set] -
Соответствует любому символу в
set. Ведет себя точно так же, как множества символов в Regexp, включая отрицание наборов ([^a-z]). -
{p,q} -
Соответствует либо литералу
pили литералуq. Эквивалентно альтернации шаблонов в регулярных выражениях.Соответствующие литералы могут иметь длину более одного символа. Может быть указано более двух литералов.
-
\ -
Экранирует следующий метасимвол.
Обратите внимание, что это означает, что вы не можете использовать обратную косую черту на Windows как часть glob, т.е.
Dir["c:\foo*"]не будет работать, используйтеDir["c:/foo*"]вместо этого.
Примеры:
Dir["config.?"] #=> ["config.h"]
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", "main.rb"]
Dir.glob("*", File::FNM_DOTMATCH) #=> [".", "..", "config.h", "main.rb"]
rbfiles = File.join("**", "*.rb")
Dir.glob(rbfiles) #=> ["main.rb",
# "lib/song.rb",
# "lib/song/karaoke.rb"]
libdirs = File.join("**", "lib")
Dir.glob(libdirs) #=> ["lib"]
librbfiles = File.join("**", "lib", "**", "*.rb")
Dir.glob(librbfiles) #=> ["lib/song.rb",
# "lib/song/karaoke.rb"]
librbfiles = File.join("**", "lib", "*.rb")
Dir.glob(librbfiles) #=> ["lib/song.rb"]
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)) {
SafeStringValue(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));
} Возвращает домашний каталог текущего пользователя или указанного пользователя, если он задан.
static VALUE
dir_s_mkdir(int argc, VALUE *argv, VALUE obj)
{
VALUE path, vmode;
int mode;
if (rb_scan_args(argc, argv, "11", &path, &vmode) == 2) {
mode = NUM2INT(vmode);
}
else {
mode = 0777;
}
check_dirname(&path);
if (mkdir(RSTRING_PTR(path), mode) == -1)
rb_sys_fail_path(path);
return INT2FIX(0);
} Создаёт новый каталог, имя которого задано в string, с правами доступа, указанными в необязательном параметре anInteger. Права доступа могут быть изменены значением File::umask, и игнорируются в NT. Вызывает SystemCallError если каталог не может быть создан. См. также обсуждение прав доступа в документации класса File.
Dir.mkdir(File.join(Dir.home, ".foo"), 0700) #=> 0
# File lib/tmpdir.rb, line 84
def Dir.mktmpdir(prefix_suffix=nil, *rest)
path = Tmpname.create(prefix_suffix || "d", *rest) {|n| mkdir(n, 0700)}
if block_given?
begin
yield path
ensure
stat = File.stat(File.dirname(path))
if stat.world_writable? and !stat.sticky?
raise ArgumentError, "parent directory is world writable but not sticky"
end
FileUtils.remove_entry path
end
else
path
end
end ::mktmpdir создаёт временную директорию.
Директория создаётся с разрешениями 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" }
Директория создаётся в ::tmpdir или необязательном втором аргументе tmpdir, если задано ненулевое значение.
Dir.mktmpdir {|dir| dir is "#{Dir.tmpdir}/d..." }
Dir.mktmpdir(nil, "/var/tmp") {|dir| dir is "/var/tmp/d..." }
Если блок указан, он вызывается с путём к директории. Директория и её содержимое удаляются с помощью FileUtils#remove_entry перед тем, как ::mktmpdir вернёт значение. Возвращаемое значение блока.
Dir.mktmpdir {|dir|
# use the directory...
open("#{dir}/foo", "w") { ... }
} Если блок не указан, возвращается путь к директории. В этом случае ::mktmpdir не удаляет директорию.
dir = Dir.mktmpdir
begin
# use the directory...
open("#{dir}/foo", "w") { ... }
ensure
# remove the directory.
FileUtils.remove_entry dir
end static VALUE
dir_initialize(int argc, VALUE *argv, VALUE dir)
{
struct dir_data *dp;
rb_encoding *fsenc;
VALUE dirname, opt, orig;
static ID keyword_ids[1];
const char *path;
if (!keyword_ids[0]) {
keyword_ids[0] = rb_intern("encoding");
}
fsenc = rb_filesystem_encoding();
rb_scan_args(argc, argv, "1:", &dirname, &opt);
if (!NIL_P(opt)) {
VALUE enc;
rb_get_kwargs(opt, keyword_ids, 0, 1, &enc);
if (enc != Qundef && !NIL_P(enc)) {
fsenc = rb_to_encoding(enc);
}
}
FilePathValue(dirname);
orig = rb_str_dup_frozen(dirname);
dirname = rb_str_encode_ospath(dirname);
dirname = rb_str_dup_frozen(dirname);
TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dp);
if (dp->dir) closedir(dp->dir);
dp->dir = NULL;
dp->path = Qnil;
dp->enc = fsenc;
path = RSTRING_PTR(dirname);
dp->dir = opendir(path);
if (dp->dir == NULL) {
if (errno == EMFILE || errno == ENFILE) {
rb_gc();
dp->dir = opendir(path);
}
#ifdef HAVE_GETATTRLIST
else if (errno == EIO) {
u_int32_t attrbuf[1];
struct attrlist al = {ATTR_BIT_MAP_COUNT, 0};
if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW) == 0) {
dp->dir = opendir(path);
}
}
#endif
if (dp->dir == NULL) {
RB_GC_GUARD(dirname);
rb_sys_fail_path(orig);
}
}
dp->path = orig;
return dir;
} Возвращает новый объект каталога для указанного каталога.
Необязательный аргумент enc задаёт кодировку каталога. Если он не указан, используется кодировка файловой системы.
static VALUE
dir_s_open(int argc, VALUE *argv, VALUE klass)
{
struct dir_data *dp;
VALUE dir = TypedData_Make_Struct(klass, struct dir_data, &dir_data_type, dp);
dir_initialize(argc, argv, dir);
if (rb_block_given_p()) {
return rb_ensure(rb_yield, dir, dir_close, dir);
}
return dir;
} Необязательный аргумент enc задаёт кодировку каталога. Если он не указан, используется кодировка файловой системы.
Без блока, open является синонимом Dir::new. Если блок присутствует, он получает aDir в качестве параметра. Каталог закрывается в конце блока, и Dir::open возвращает значение блока.
static VALUE
dir_s_getwd(VALUE dir)
{
return rb_dir_getwd();
} Возвращает путь к текущей рабочей директории этого процесса в виде строки.
Dir.chdir("/tmp") #=> 0
Dir.getwd #=> "/tmp"
Dir.pwd #=> "/tmp"
static VALUE
dir_s_rmdir(VALUE obj, VALUE dir)
{
check_dirname(&dir);
if (rmdir(RSTRING_PTR(dir)) < 0)
rb_sys_fail_path(dir);
return INT2FIX(0);
} Удаляет указанный каталог. Вызывает подкласс SystemCallError, если каталог не пуст.
# File lib/tmpdir.rb, line 20
def self.tmpdir
if $SAFE > 0
@@systmpdir
else
tmp = nil
[ENV['TMPDIR'], ENV['TMP'], ENV['TEMP'], @@systmpdir, '/tmp', '.'].each do |dir|
next if !dir
dir = File.expand_path(dir)
if stat = File.stat(dir) and stat.directory? and stat.writable? and
(!stat.world_writable? or stat.sticky?)
tmp = dir
break
end rescue nil
end
raise ArgumentError, "could not find a temporary directory" unless tmp
tmp
end
end Возвращает временный путь к файлу операционной системы.
static VALUE
dir_s_rmdir(VALUE obj, VALUE dir)
{
check_dirname(&dir);
if (rmdir(RSTRING_PTR(dir)) < 0)
rb_sys_fail_path(dir);
return INT2FIX(0);
} Удаляет указанный каталог. Вызывает подкласс SystemCallError, если каталог не пуст.
Общедоступные методы экземпляров
static VALUE
dir_close(VALUE dir)
{
struct dir_data *dirp;
GetDIR(dir, dirp);
closedir(dirp->dir);
dirp->dir = NULL;
return Qnil;
} Закрывает поток каталога. Любые дальнейшие попытки доступа к dir вызовут IOError.
d = Dir.new("testdir")
d.close #=> nil
static VALUE
dir_each(VALUE dir)
{
struct dir_data *dirp;
struct dirent *dp;
IF_NORMALIZE_UTF8PATH(int norm_p);
RETURN_ENUMERATOR(dir, 0, 0);
GetDIR(dir, dirp);
rewinddir(dirp->dir);
IF_NORMALIZE_UTF8PATH(norm_p = need_normalization(dirp->dir, RSTRING_PTR(dirp->path)));
while ((dp = READDIR(dirp->dir, dirp->enc)) != NULL) {
const char *name = dp->d_name;
size_t namlen = NAMLEN(dp);
VALUE path;
#if NORMALIZE_UTF8PATH
if (norm_p && has_nonascii(name, namlen) &&
!NIL_P(path = rb_str_normalize_ospath(name, namlen))) {
path = rb_external_str_with_enc(path, dirp->enc);
}
else
#endif
path = rb_external_str_new_with_enc(name, namlen, dirp->enc);
rb_yield(path);
if (dirp->dir == NULL) dir_closed();
}
return dir;
} Вызывает блок один раз для каждого элемента в этом каталоге, передавая имя файла каждого элемента в качестве параметра блоку.
Если блок не указан, вместо этого возвращается перечислитель.
d = Dir.new("testdir")
d.each {|x| puts "Got #{x}" }
возвращает:
Got . Got .. Got config.h Got main.rb
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. На других платформах, таких как Windows, которая не предоставляет функцию, возникает исключение NotImplementedError.
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_funcall(dir, rb_intern("to_s"), 0, 0);
} Возвращает строку, описывающую этот объект Dir.
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);
} Возвращает параметр пути, переданный конструктору dir.
d = Dir.new("..")
d.path #=> ".."
static VALUE
dir_tell(VALUE dir)
{
struct dir_data *dirp;
long pos;
GetDIR(dir, dirp);
pos = telldir(dirp->dir);
return rb_int2inum(pos);
} Возвращает текущую позицию в dir. См. также Dir#seek.
d = Dir.new("testdir")
d.tell #=> 0
d.read #=> "."
d.tell #=> 12
static VALUE
dir_set_pos(VALUE dir, VALUE pos)
{
dir_seek(dir, pos);
return pos;
} Синоним для Dir#seek, но возвращает параметр позиции.
d = Dir.new("testdir") #=> #<Dir:0x401b3c40>
d.read #=> "."
i = d.pos #=> 12
d.read #=> ".."
d.pos = i #=> 12
d.read #=> ".."
static VALUE
dir_read(VALUE dir)
{
struct dir_data *dirp;
struct dirent *dp;
GetDIR(dir, dirp);
errno = 0;
if ((dp = READDIR(dirp->dir, dirp->enc)) != NULL) {
return rb_external_str_new_with_enc(dp->d_name, NAMLEN(dp), dirp->enc);
}
else {
if (errno != 0) rb_sys_fail(0);
return Qnil; /* end of stream */
}
} Считывает следующий элемент из dir и возвращает его в виде строки. Возвращает nil в конце потока.
d = Dir.new("testdir")
d.read #=> "."
d.read #=> ".."
d.read #=> "config.h"
static VALUE
dir_rewind(VALUE dir)
{
struct dir_data *dirp;
GetDIR(dir, dirp);
rewinddir(dirp->dir);
return dir;
} Перемещает dir к первому элементу.
d = Dir.new("testdir")
d.read #=> "."
d.rewind #=> #<Dir:0x401b3fb0>
d.read #=> "."
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;
} Перемещает указатель в определённую позицию в dir. integer должен быть значением, возвращаемым Dir#tell.
d = Dir.new("testdir") #=> #<Dir:0x401b3c40>
d.read #=> "."
i = d.tell #=> 12
d.read #=> ".."
d.seek(i) #=> #<Dir:0x401b3c40>
d.read #=> ".."
static VALUE
dir_tell(VALUE dir)
{
struct dir_data *dirp;
long pos;
GetDIR(dir, dirp);
pos = telldir(dirp->dir);
return rb_int2inum(pos);
} Возвращает текущую позицию в dir. См. также Dir#seek.
d = Dir.new("testdir")
d.tell #=> 0
d.read #=> "."
d.tell #=> 12
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);
} Возвращает параметр пути, переданный конструктору dir.
d = Dir.new("..")
d.path #=> ".."
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.