класс File
A File — это абстракция любого файла, доступного программе, и тесно связана с классом IO. File включает методы модуля FileTest в качестве методов класса, что позволяет, например, File.exist?("foo").
В описании методов File, разрешения — это зависящий от платформы набор битов, указывающий разрешения файла. В системах на основе Unix разрешения представляются набором из трёх октетов для владельца, группы и остальных пользователей. Для каждой из этих сущностей разрешения могут быть установлены на чтение, запись или выполнение файла:
Разрешения 0644 (в восьмеричной форме) означают чтение/запись для владельца и только чтение для группы и других пользователей. Старшие биты также могут использоваться для указания типа файла (обычный, каталог, канал, сокет и т. д.) и различных других специальных функций. Если разрешения относятся к каталогу, значение бита выполнения изменяется; при его установке каталог можно перебирать.
В не-Posix операционных системах может быть только возможность сделать файл только для чтения или для чтения/записи. В этом случае оставшиеся биты разрешений будут синтезированы, чтобы соответствовать типичным значениям. Например, в Windows NT стандартные биты разрешений — 0644, что означает чтение/запись для владельца и только чтение для всех остальных. Единственное изменение, которое может быть сделано, — это сделать файл только для чтения, что отражается как 0444.
Различные константы для методов в File можно найти в File::Constants.
Константы
- ALT_SEPARATOR
-
специфический для платформы альтернативный разделитель
- PATH_SEPARATOR
-
разделитель списка путей
- SEPARATOR
-
разделяет части каталога в пути
- Separator
-
разделяет части каталога в пути
Публичные методы класса
VALUE
rb_file_s_absolute_path(int argc, const VALUE *argv)
{
VALUE fname, dname;
if (argc == 1) {
return rb_file_absolute_path(argv[0], Qnil);
}
rb_scan_args(argc, argv, "11", &fname, &dname);
return rb_file_absolute_path(fname, dname);
} Преобразует имя файла в абсолютный путь. Относительные пути указываются из текущего рабочего каталога процесса, если только не задан dir_string, в этом случае он будет использован в качестве начальной точки. Если заданное имя файла начинается с “~'' оно НЕ раскрывается, а обрабатывается как обычное имя каталога.
File.absolute_path("~oracle/bin") #=> "<relative_path>/~oracle/bin"
static VALUE
rb_file_s_atime(VALUE klass, VALUE fname)
{
struct stat st;
if (rb_stat(fname, &st) < 0) {
int e = errno;
FilePathValue(fname);
rb_syserr_fail_path(e, fname);
}
return stat_atime(&st);
} Возвращает время последнего доступа к указанному файлу в виде объекта Time.
file_name может быть объектом IO.
File.atime("testfile") #=> Wed Apr 09 08:51:48 CDT 2003
static VALUE
rb_file_s_basename(int argc, VALUE *argv)
{
VALUE fname, fext, basename;
const char *name, *p;
long f, n;
rb_encoding *enc;
if (rb_scan_args(argc, argv, "11", &fname, &fext) == 2) {
StringValue(fext);
enc = check_path_encoding(fext);
}
FilePathStringValue(fname);
if (NIL_P(fext) || !(enc = rb_enc_compatible(fname, fext))) {
enc = rb_enc_get(fname);
fext = Qnil;
}
if ((n = RSTRING_LEN(fname)) == 0 || !*(name = RSTRING_PTR(fname)))
return rb_str_new_shared(fname);
p = ruby_enc_find_basename(name, &f, &n, enc);
if (n >= 0) {
if (NIL_P(fext)) {
f = n;
}
else {
const char *fp;
fp = StringValueCStr(fext);
if (!(f = rmext(p, f, n, fp, RSTRING_LEN(fext), enc))) {
f = n;
}
RB_GC_GUARD(fext);
}
if (f == RSTRING_LEN(fname)) return rb_str_new_shared(fname);
}
basename = rb_str_new(p, f);
rb_enc_copy(basename, fname);
OBJ_INFECT(basename, fname);
return basename;
} Возвращает последний компонент имени файла, заданного в file_name, который может быть сформирован с использованием как File::SEPARATOR так и File::ALT_SEPARATOR в качестве разделителя, когда File::ALT_SEPARATOR не nil. Если suffix задан и присутствует в конце file_name, он удаляется. Если suffix равен “.*”, любое расширение будет удалено.
File.basename("/home/gumby/work/ruby.rb") #=> "ruby.rb"
File.basename("/home/gumby/work/ruby.rb", ".rb") #=> "ruby"
File.basename("/home/gumby/work/ruby.rb", ".*") #=> "ruby"
static VALUE
rb_file_s_birthtime(VALUE klass, VALUE fname)
{
struct stat st;
if (rb_stat(fname, &st) < 0) {
int e = errno;
FilePathValue(fname);
rb_syserr_fail_path(e, fname);
}
return stat_birthtime(&st);
} Возвращает время создания для указанного файла.
file_name может быть объектом IO.
File.birthtime("testfile") #=> Wed Apr 09 08:53:13 CDT 2003
Если платформа не поддерживает время создания, возникает исключение NotImplementedError.
static VALUE
rb_file_blockdev_p(VALUE obj, VALUE fname)
{
#ifndef S_ISBLK
# ifdef S_IFBLK
# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
# else
# define S_ISBLK(m) (0) /* anytime false */
# endif
#endif
#ifdef S_ISBLK
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISBLK(st.st_mode)) return Qtrue;
#endif
return Qfalse;
} Возвращает true если указанный файл является блочным устройством.
file_name может быть объектом IO.
static VALUE
rb_file_chardev_p(VALUE obj, VALUE fname)
{
#ifndef S_ISCHR
# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#endif
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISCHR(st.st_mode)) return Qtrue;
return Qfalse;
} Возвращает true если указанный файл является символьным устройством.
file_name может быть объектом IO.
static VALUE
rb_file_s_chmod(int argc, VALUE *argv)
{
VALUE vmode;
VALUE rest;
int mode;
long n;
rb_scan_args(argc, argv, "1*", &vmode, &rest);
mode = NUM2INT(vmode);
n = apply2files(chmod_internal, rest, &mode);
return LONG2FIX(n);
} Изменяет биты разрешений в указанных файлах на битовую маску, представленную mode_int. Фактические эффекты зависят от операционной системы (см. начало этого раздела). В Unix-системах, см. chmod(2) для подробностей. Возвращает количество обработанных файлов.
File.chmod(0644, "testfile", "out") #=> 2
static VALUE
rb_file_s_chown(int argc, VALUE *argv)
{
VALUE o, g, rest;
struct chown_args arg;
long n;
rb_scan_args(argc, argv, "2*", &o, &g, &rest);
arg.owner = to_uid(o);
arg.group = to_gid(g);
n = apply2files(chown_internal, rest, &arg);
return LONG2FIX(n);
} Изменяет владельца и группу указанных файлов на заданные числовые идентификаторы владельца и группы. Только процесс с правами суперпользователя может изменить владельца файла. Текущий владелец файла может изменить группу файла на любую группу, к которой принадлежит владелец. nil или -1 идентификатор владельца или группы игнорируется. Возвращает количество обработанных файлов.
File.chown(nil, 100, "testfile")
static VALUE
rb_file_s_ctime(VALUE klass, VALUE fname)
{
struct stat st;
if (rb_stat(fname, &st) < 0) {
int e = errno;
FilePathValue(fname);
rb_syserr_fail_path(e, fname);
}
return stat_ctime(&st);
} Возвращает время изменения для указанного файла (время, когда менялась информация о каталоге файла, а не сам файл).
file_name может быть объектом IO.
Обратите внимание, что в Windows (NTFS) возвращается время создания.
File.ctime("testfile") #=> Wed Apr 09 08:53:13 CDT 2003
static VALUE
rb_file_s_unlink(VALUE klass, VALUE args)
{
long n;
n = apply2files(unlink_internal, args, 0);
return LONG2FIX(n);
} Удаляет указанные файлы, возвращая количество имен, переданных в качестве аргументов. В случае любой ошибки возникает исключение. См. также Dir::rmdir.
VALUE
rb_file_directory_p(VALUE obj, VALUE fname)
{
#ifndef S_ISDIR
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISDIR(st.st_mode)) return Qtrue;
return Qfalse;
} Возвращает true если указанный файл является каталогом или символической ссылкой, указывающей на каталог, и false в противном случае.
file_name может быть объектом IO.
File.directory?(".")
static VALUE
rb_file_s_dirname(VALUE klass, VALUE fname)
{
return rb_file_dirname(fname);
} Возвращает все компоненты имени файла, заданного в file_name, кроме последнего. Имя файла может быть сформировано с использованием как File::SEPARATOR так и File::ALT_SEPARATOR в качестве разделителя, когда File::ALT_SEPARATOR не nil.
File.dirname("/home/gumby/work/ruby.rb") #=> "/home/gumby/work"
static VALUE
rb_file_executable_p(VALUE obj, VALUE fname)
{
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
if (eaccess(StringValueCStr(fname), X_OK) < 0) return Qfalse;
return Qtrue;
} Возвращает true если указанный файл исполняемый для эффективного идентификатора пользователя и группы этого процесса. См. eaccess(3).
static VALUE
rb_file_executable_real_p(VALUE obj, VALUE fname)
{
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
if (access(StringValueCStr(fname), X_OK) < 0) return Qfalse;
return Qtrue;
} Возвращает true если указанный файл исполняемый для реального идентификатора пользователя и группы этого процесса. См. access(3).
static VALUE
rb_file_exist_p(VALUE obj, VALUE fname)
{
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
return Qtrue;
} Возвращает true если указанный файл существует.
file_name может быть объектом IO.
“Файл существует” означает, что системный вызов stat() или fstat() выполнен успешно.
static VALUE
rb_file_exists_p(VALUE obj, VALUE fname)
{
const char *s = "FileTest#";
if (obj == rb_mFileTest) {
s = "FileTest.";
}
else if (obj == rb_cFile ||
(RB_TYPE_P(obj, T_CLASS) &&
RTEST(rb_class_inherited_p(obj, rb_cFile)))) {
s = "File.";
}
rb_warning("%sexists? is a deprecated name, use %sexist? instead", s, s);
return rb_file_exist_p(obj, fname);
} Устаревший метод. Не использовать.
VALUE
rb_file_s_expand_path(int argc, const VALUE *argv)
{
VALUE fname, dname;
if (argc == 1) {
return rb_file_expand_path(argv[0], Qnil);
}
rb_scan_args(argc, argv, "11", &fname, &dname);
return rb_file_expand_path(fname, dname);
} Преобразует имя файла в абсолютный путь. Относительные пути указываются из текущего рабочего каталога процесса, если только не задан dir_string, в этом случае он будет использован в качестве начальной точки. Заданное имя файла может начинаться с “~'', которое раскрывается в домашний каталог владельца процесса (переменная среды HOME должна быть установлена правильно). “~user'' раскрывается в домашний каталог указанного пользователя.
File.expand_path("~oracle/bin") #=> "/home/oracle/bin"
Простой пример использования dir_string выглядит следующим образом.
File.expand_path("ruby", "/usr/bin") #=> "/usr/bin/ruby"
Более сложный пример, который также разрешает родительский каталог, выглядит следующим образом. Предположим, мы находимся в bin/mygem и хотим получить абсолютный путь lib/mygem.rb.
File.expand_path("../../lib/mygem.rb", __FILE__)
#=> ".../path/to/project/lib/mygem.rb"
Сначала он разрешает родителя __FILE__, то есть bin/, затем переходит к родителю, корню проекта и добавляет lib/mygem.rb.
static VALUE
rb_file_s_extname(VALUE klass, VALUE fname)
{
const char *name, *e;
long len;
VALUE extname;
FilePathStringValue(fname);
name = StringValueCStr(fname);
len = RSTRING_LEN(fname);
e = ruby_enc_find_extname(name, &len, rb_enc_get(fname));
if (len <= 1)
return rb_str_new(0, 0);
extname = rb_str_subseq(fname, e - name, len); /* keep the dot, too! */
OBJ_INFECT(extname, fname);
return extname;
} Возвращает расширение (часть имени файла в path начиная с последней точки).
Если path является файлом с точкой или начинается с точки, то начальная точка не обрабатывается как начало расширения.
Пустая строка также будет возвращена, когда точка является последним символом в path.
File.extname("test.rb") #=> ".rb"
File.extname("a/b/d/test.rb") #=> ".rb"
File.extname(".a/b/d/test.rb") #=> ".rb"
File.extname("foo.") #=> ""
File.extname("test") #=> ""
File.extname(".profile") #=> ""
File.extname(".profile.sh") #=> ".sh"
static VALUE
rb_file_file_p(VALUE obj, VALUE fname)
{
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISREG(st.st_mode)) return Qtrue;
return Qfalse;
} Возвращает true, если указанный файл существует и является обычным файлом.
Аргумент может быть объектом IO.
Если аргумент является символической ссылкой, она будет разрешена, и будет использован файл, на который указывает ссылка.
static VALUE
file_s_fnmatch(int argc, VALUE *argv, VALUE obj)
{
VALUE pattern, path;
VALUE rflags;
int flags;
if (rb_scan_args(argc, argv, "21", &pattern, &path, &rflags) == 3)
flags = NUM2INT(rflags);
else
flags = 0;
StringValue(pattern);
FilePathStringValue(path);
if (flags & FNM_EXTGLOB) {
struct brace_args args;
args.value = path;
args.flags = flags;
if (ruby_brace_expand(RSTRING_PTR(pattern), flags, fnmatch_brace,
(VALUE)&args, rb_enc_get(pattern)) > 0)
return Qtrue;
}
else {
rb_encoding *enc = rb_enc_compatible(pattern, path);
if (!enc) return Qfalse;
if (fnmatch(RSTRING_PTR(pattern), enc, RSTRING_PTR(path), flags) == 0)
return Qtrue;
}
RB_GC_GUARD(pattern);
return Qfalse;
} Возвращает true, если шаблон соответствует пути. Шаблон не является регулярным выражением; вместо этого он следует правилам, похожим на подстановку имен файлов в оболочке. Он может содержать следующие метасимволы:
-
* -
Соответствует любому файлу. Может быть ограничено другими значениями в шаблоне. Эквивалентно
/ .* /xв регулярных выражениях.-
* -
Соответствует всем обычным файлам
-
c* -
Соответствует всем файлам, начинающимся с
c -
*c -
Соответствует всем файлам, заканчивающимся на
c -
*c* -
Соответствует всем файлам, содержащим
c(включая начало и конец).
Чтобы сопоставить скрытые файлы (начинающиеся с точки), установите флаг File::FNM_DOTMATCH.
-
-
** -
Соответствует каталогам рекурсивно или файлам расширительно.
-
? -
Соответствует любому одному символу. Эквивалентно
/.{1}/в регулярных выражениях. -
[set] -
Соответствует любому одному символу в
set. Ведёт себя точно так же, как наборы символов в Regexp, включая отрицание наборов ([^a-z]). -
\ -
Экранирует следующий метасимвол.
-
{a,b} -
Соответствует шаблону a и шаблону b, если установлен флаг File::FNM_EXTGLOB. Поведение аналогично объединению в Regexp (
(?:a|b)).
flags — это побитовое ИЛИ констант FNM_XXX. Тот же шаблон и флаги используются методом Dir.glob.
Примеры:
File.fnmatch('cat', 'cat') #=> true # match entire string
File.fnmatch('cat', 'category') #=> false # only match partial string
File.fnmatch('c{at,ub}s', 'cats') #=> false # { } isn't supported by default
File.fnmatch('c{at,ub}s', 'cats', File::FNM_EXTGLOB) #=> true # { } is supported on FNM_EXTGLOB
File.fnmatch('c?t', 'cat') #=> true # '?' match only 1 character
File.fnmatch('c??t', 'cat') #=> false # ditto
File.fnmatch('c*', 'cats') #=> true # '*' match 0 or more characters
File.fnmatch('c*t', 'c/a/b/t') #=> true # ditto
File.fnmatch('ca[a-z]', 'cat') #=> true # inclusive bracket expression
File.fnmatch('ca[^t]', 'cat') #=> false # exclusive bracket expression ('^' or '!')
File.fnmatch('cat', 'CAT') #=> false # case sensitive
File.fnmatch('cat', 'CAT', File::FNM_CASEFOLD) #=> true # case insensitive
File.fnmatch('?', '/', File::FNM_PATHNAME) #=> false # wildcard doesn't match '/' on FNM_PATHNAME
File.fnmatch('*', '/', File::FNM_PATHNAME) #=> false # ditto
File.fnmatch('[/]', '/', File::FNM_PATHNAME) #=> false # ditto
File.fnmatch('\?', '?') #=> true # escaped wildcard becomes ordinary
File.fnmatch('\a', 'a') #=> true # escaped ordinary remains ordinary
File.fnmatch('\a', '\a', File::FNM_NOESCAPE) #=> true # FNM_NOESCAPE makes '\' ordinary
File.fnmatch('[\?]', '?') #=> true # can escape inside bracket expression
File.fnmatch('*', '.profile') #=> false # wildcard doesn't match leading
File.fnmatch('*', '.profile', File::FNM_DOTMATCH) #=> true # period by default.
File.fnmatch('.*', '.profile') #=> true
rbfiles = '**' '/' '*.rb' # you don't have to do like this. just write in single string.
File.fnmatch(rbfiles, 'main.rb') #=> false
File.fnmatch(rbfiles, './main.rb') #=> false
File.fnmatch(rbfiles, 'lib/song.rb') #=> true
File.fnmatch('**.rb', 'main.rb') #=> true
File.fnmatch('**.rb', './main.rb') #=> false
File.fnmatch('**.rb', 'lib/song.rb') #=> true
File.fnmatch('*', 'dave/.profile') #=> true
pattern = '*' '/' '*'
File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME) #=> false
File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
pattern = '**' '/' 'foo'
File.fnmatch(pattern, 'a/b/c/foo', File::FNM_PATHNAME) #=> true
File.fnmatch(pattern, '/a/b/c/foo', File::FNM_PATHNAME) #=> true
File.fnmatch(pattern, 'c:/a/b/c/foo', File::FNM_PATHNAME) #=> true
File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME) #=> false
File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
static VALUE
file_s_fnmatch(int argc, VALUE *argv, VALUE obj)
{
VALUE pattern, path;
VALUE rflags;
int flags;
if (rb_scan_args(argc, argv, "21", &pattern, &path, &rflags) == 3)
flags = NUM2INT(rflags);
else
flags = 0;
StringValue(pattern);
FilePathStringValue(path);
if (flags & FNM_EXTGLOB) {
struct brace_args args;
args.value = path;
args.flags = flags;
if (ruby_brace_expand(RSTRING_PTR(pattern), flags, fnmatch_brace,
(VALUE)&args, rb_enc_get(pattern)) > 0)
return Qtrue;
}
else {
rb_encoding *enc = rb_enc_compatible(pattern, path);
if (!enc) return Qfalse;
if (fnmatch(RSTRING_PTR(pattern), enc, RSTRING_PTR(path), flags) == 0)
return Qtrue;
}
RB_GC_GUARD(pattern);
return Qfalse;
} Возвращает true, если шаблон соответствует пути. Шаблон не является регулярным выражением; вместо этого он следует правилам, похожим на подстановку имен файлов в оболочке. Он может содержать следующие метасимволы:
-
* -
Соответствует любому файлу. Может быть ограничено другими значениями в шаблоне. Эквивалентно
/ .* /xв регулярных выражениях.-
* -
Соответствует всем обычным файлам
-
c* -
Соответствует всем файлам, начинающимся с
c -
*c -
Соответствует всем файлам, заканчивающимся на
c -
*c* -
Соответствует всем файлам, содержащим
c(включая начало и конец).
Чтобы сопоставить скрытые файлы (начинающиеся с точки), установите флаг File::FNM_DOTMATCH.
-
-
** -
Соответствует каталогам рекурсивно или файлам расширительно.
-
? -
Соответствует любому одному символу. Эквивалентно
/.{1}/в регулярных выражениях. -
[set] -
Соответствует любому одному символу в
set. Ведёт себя точно так же, как наборы символов в Regexp, включая отрицание наборов ([^a-z]). -
\ -
Экранирует следующий метасимвол.
-
{a,b} -
Соответствует шаблону a и шаблону b, если установлен флаг File::FNM_EXTGLOB. Поведение аналогично объединению в Regexp (
(?:a|b)).
flags — это побитовое ИЛИ констант FNM_XXX. Тот же шаблон и флаги используются методом Dir.glob.
Примеры:
File.fnmatch('cat', 'cat') #=> true # match entire string
File.fnmatch('cat', 'category') #=> false # only match partial string
File.fnmatch('c{at,ub}s', 'cats') #=> false # { } isn't supported by default
File.fnmatch('c{at,ub}s', 'cats', File::FNM_EXTGLOB) #=> true # { } is supported on FNM_EXTGLOB
File.fnmatch('c?t', 'cat') #=> true # '?' match only 1 character
File.fnmatch('c??t', 'cat') #=> false # ditto
File.fnmatch('c*', 'cats') #=> true # '*' match 0 or more characters
File.fnmatch('c*t', 'c/a/b/t') #=> true # ditto
File.fnmatch('ca[a-z]', 'cat') #=> true # inclusive bracket expression
File.fnmatch('ca[^t]', 'cat') #=> false # exclusive bracket expression ('^' or '!')
File.fnmatch('cat', 'CAT') #=> false # case sensitive
File.fnmatch('cat', 'CAT', File::FNM_CASEFOLD) #=> true # case insensitive
File.fnmatch('?', '/', File::FNM_PATHNAME) #=> false # wildcard doesn't match '/' on FNM_PATHNAME
File.fnmatch('*', '/', File::FNM_PATHNAME) #=> false # ditto
File.fnmatch('[/]', '/', File::FNM_PATHNAME) #=> false # ditto
File.fnmatch('\?', '?') #=> true # escaped wildcard becomes ordinary
File.fnmatch('\a', 'a') #=> true # escaped ordinary remains ordinary
File.fnmatch('\a', '\a', File::FNM_NOESCAPE) #=> true # FNM_NOESCAPE makes '\' ordinary
File.fnmatch('[\?]', '?') #=> true # can escape inside bracket expression
File.fnmatch('*', '.profile') #=> false # wildcard doesn't match leading
File.fnmatch('*', '.profile', File::FNM_DOTMATCH) #=> true # period by default.
File.fnmatch('.*', '.profile') #=> true
rbfiles = '**' '/' '*.rb' # you don't have to do like this. just write in single string.
File.fnmatch(rbfiles, 'main.rb') #=> false
File.fnmatch(rbfiles, './main.rb') #=> false
File.fnmatch(rbfiles, 'lib/song.rb') #=> true
File.fnmatch('**.rb', 'main.rb') #=> true
File.fnmatch('**.rb', './main.rb') #=> false
File.fnmatch('**.rb', 'lib/song.rb') #=> true
File.fnmatch('*', 'dave/.profile') #=> true
pattern = '*' '/' '*'
File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME) #=> false
File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
pattern = '**' '/' 'foo'
File.fnmatch(pattern, 'a/b/c/foo', File::FNM_PATHNAME) #=> true
File.fnmatch(pattern, '/a/b/c/foo', File::FNM_PATHNAME) #=> true
File.fnmatch(pattern, 'c:/a/b/c/foo', File::FNM_PATHNAME) #=> true
File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME) #=> false
File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
static VALUE
rb_file_s_ftype(VALUE klass, VALUE fname)
{
struct stat st;
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
if (lstat(StringValueCStr(fname), &st) == -1) {
rb_sys_fail_path(fname);
}
return rb_file_ftype(&st);
} Определяет тип указанного файла; возвращаемая строка — одна из «file», «directory», «characterSpecial», «blockSpecial», «fifo», «link», «socket» или «unknown».
File.ftype("testfile") #=> "file"
File.ftype("/dev/tty") #=> "characterSpecial"
File.ftype("/tmp/.X11-unix/X0") #=> "socket"
static VALUE
rb_file_grpowned_p(VALUE obj, VALUE fname)
{
#ifndef _WIN32
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (rb_group_member(st.st_gid)) return Qtrue;
#endif
return Qfalse;
} Возвращает true, если указанный файл существует и эффективная группа id вызывающего процесса совпадает с владельцем файла. Возвращает false в Windows.
имя_файла может быть объектом IO.
static VALUE
rb_file_identical_p(VALUE obj, VALUE fname1, VALUE fname2)
{
#ifndef _WIN32
struct stat st1, st2;
if (rb_stat(fname1, &st1) < 0) return Qfalse;
if (rb_stat(fname2, &st2) < 0) return Qfalse;
if (st1.st_dev != st2.st_dev) return Qfalse;
if (st1.st_ino != st2.st_ino) return Qfalse;
return Qtrue;
#else
BY_HANDLE_FILE_INFORMATION st1, st2;
HANDLE f1 = 0, f2 = 0;
f1 = w32_io_info(&fname1, &st1);
if (f1 == INVALID_HANDLE_VALUE) return Qfalse;
if (f1) {
struct w32_io_info_args arg;
arg.fname = &fname2;
arg.st = &st2;
f2 = (HANDLE)rb_ensure(call_w32_io_info, (VALUE)&arg, close_handle, (VALUE)f1);
}
else {
f2 = w32_io_info(&fname2, &st2);
}
if (f2 == INVALID_HANDLE_VALUE) return Qfalse;
if (f2) CloseHandle(f2);
if (st1.dwVolumeSerialNumber == st2.dwVolumeSerialNumber &&
st1.nFileIndexHigh == st2.nFileIndexHigh &&
st1.nFileIndexLow == st2.nFileIndexLow)
return Qtrue;
return Qfalse;
#endif
} Возвращает true, если указанные файлы идентичны.
файл_1 и файл_2 могут быть объектами IO.
open("a", "w") {}
p File.identical?("a", "a") #=> true
p File.identical?("a", "./a") #=> true
File.link("a", "b")
p File.identical?("a", "b") #=> true
File.symlink("a", "c")
p File.identical?("a", "c") #=> true
open("d", "w") {}
p File.identical?("a", "d") #=> false
static VALUE
rb_file_s_join(VALUE klass, VALUE args)
{
return rb_file_join(args, separator);
} Возвращает новую строку, образованную путём объединения строк с помощью разделителя.
File.join("usr", "mail", "gumby") #=> "usr/mail/gumby"
static VALUE
rb_file_s_lchmod(int argc, VALUE *argv)
{
VALUE vmode;
VALUE rest;
long mode, n;
rb_scan_args(argc, argv, "1*", &vmode, &rest);
mode = NUM2INT(vmode);
n = apply2files(lchmod_internal, rest, (void *)(long)mode);
return LONG2FIX(n);
} Эквивалентно File::chmod, но не следует за символическими ссылками (меняет права, связанные со ссылкой, а не с файлом, на который она указывает). Часто недоступно.
static VALUE
rb_file_s_lchown(int argc, VALUE *argv)
{
VALUE o, g, rest;
struct chown_args arg;
long n;
rb_scan_args(argc, argv, "2*", &o, &g, &rest);
arg.owner = to_uid(o);
arg.group = to_gid(g);
n = apply2files(lchown_internal, rest, &arg);
return LONG2FIX(n);
} Эквивалентно File::chown, но не следует за символическими ссылками (меняет владельца, связанного со ссылкой, а не с файлом, на который она указывает). Часто недоступно. Возвращает количество файлов в списке аргументов.
static VALUE
rb_file_s_link(VALUE klass, VALUE from, VALUE to)
{
FilePathValue(from);
FilePathValue(to);
from = rb_str_encode_ospath(from);
to = rb_str_encode_ospath(to);
if (link(StringValueCStr(from), StringValueCStr(to)) < 0) {
sys_fail2(from, to);
}
return INT2FIX(0);
} Создаёт новое имя для существующего файла с помощью жёсткой ссылки. Не перезаписывает новое_имя, если оно уже существует (выбрасывает исключение, наследующее от SystemCallError). Недоступно на всех платформах.
File.link("testfile", ".testfile") #=> 0
IO.readlines(".testfile")[0] #=> "This is line one\n"
static VALUE
rb_file_s_lstat(VALUE klass, VALUE fname)
{
#ifdef HAVE_LSTAT
struct stat st;
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
if (lstat(StringValueCStr(fname), &st) == -1) {
rb_sys_fail_path(fname);
}
return rb_stat_new(&st);
#else
return rb_file_s_stat(klass, fname);
#endif
} Аналогично File::stat, но не следует за последней символической ссылкой. Вместо этого сообщает о самой ссылке.
File.symlink("testfile", "link2test") #=> 0
File.stat("testfile").size #=> 66
File.lstat("link2test").size #=> 8
File.stat("link2test").size #=> 66
static VALUE
rb_file_s_mkfifo(int argc, VALUE *argv)
{
VALUE path;
int mode = 0666;
rb_check_arity(argc, 1, 2);
if (argc > 1) {
mode = NUM2INT(argv[1]);
}
path = argv[0];
FilePathValue(path);
path = rb_str_encode_ospath(path);
if (mkfifo(RSTRING_PTR(path), mode)) {
rb_sys_fail_path(path);
}
return INT2FIX(0);
} static VALUE
rb_file_s_mtime(VALUE klass, VALUE fname)
{
struct stat st;
if (rb_stat(fname, &st) < 0) {
int e = errno;
FilePathValue(fname);
rb_syserr_fail_path(e, fname);
}
return stat_mtime(&st);
} Возвращает время изменения файла в виде объекта Time.
имя_файла может быть объектом IO.
File.mtime("testfile") #=> Tue Apr 08 12:58:04 CDT 2003
static VALUE
rb_file_initialize(int argc, VALUE *argv, VALUE io)
{
if (RFILE(io)->fptr) {
rb_raise(rb_eRuntimeError, "reinitializing File");
}
if (0 < argc && argc < 3) {
VALUE fd = rb_check_convert_type(argv[0], T_FIXNUM, "Fixnum", "to_int");
if (!NIL_P(fd)) {
argv[0] = fd;
return rb_io_initialize(argc, argv, io);
}
}
rb_open_file(argc, argv, io);
return io;
} Открывает файл, указанный filename, в соответствии с заданным mode и возвращает новый объект File.
См. IO.new для описания mode и opt.
Если создается файл, биты разрешений могут быть заданы в perm. Эти биты режима и разрешения зависят от платформы; в Unix-системах см. страницы руководства open(2) и chmod(2) для получения подробной информации.
Примеры
f = File.new("testfile", "r")
f = File.new("newfile", "w+")
f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
static VALUE
rb_io_s_open(int argc, VALUE *argv, VALUE klass)
{
VALUE io = rb_class_new_instance(argc, argv, klass);
if (rb_block_given_p()) {
return rb_ensure(rb_yield, io, io_close, io);
}
return io;
} Без связанного блока, File.open является синонимом для ::new. Если задан необязательный блок кода, ему будет передан открытый file в качестве аргумента, и объект File будет автоматически закрыт по завершении блока. Значение блока будет возвращено из File.open.
Если создается файл, его начальные разрешения могут быть установлены с помощью параметра perm. См. ::new для дальнейшего обсуждения.
См. IO.new для описания параметров mode и opt.
static VALUE
rb_file_owned_p(VALUE obj, VALUE fname)
{
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (st.st_uid == geteuid()) return Qtrue;
return Qfalse;
} Возвращает true, если указанный файл существует, и эффективный идентификатор пользователя вызывающего процесса является владельцем файла.
file_name может быть объектом IO.
static VALUE
rb_file_s_path(VALUE klass, VALUE fname)
{
return rb_get_path(fname);
} Возвращает строковое представление пути
File.path("/dev/null") #=> "/dev/null"
File.path(Pathname.new("/tmp")) #=> "/tmp"
static VALUE
rb_file_pipe_p(VALUE obj, VALUE fname)
{
#ifdef S_IFIFO
# ifndef S_ISFIFO
# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
# endif
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISFIFO(st.st_mode)) return Qtrue;
#endif
return Qfalse;
} Возвращает true, если указанный файл является каналом.
file_name может быть объектом IO.
static VALUE
rb_file_readable_p(VALUE obj, VALUE fname)
{
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
if (eaccess(StringValueCStr(fname), R_OK) < 0) return Qfalse;
return Qtrue;
} Возвращает true, если указанный файл доступен для чтения эффективным идентификатором пользователя и группы этого процесса. См. eaccess(3).
static VALUE
rb_file_readable_real_p(VALUE obj, VALUE fname)
{
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
if (access(StringValueCStr(fname), R_OK) < 0) return Qfalse;
return Qtrue;
} Возвращает true, если указанный файл доступен для чтения реальным идентификатором пользователя и группы этого процесса. См. access(3).
static VALUE
rb_file_s_readlink(VALUE klass, VALUE path)
{
return rb_readlink(path, rb_filesystem_encoding());
} Возвращает имя файла, на который ссылается данная ссылка. Доступно не на всех платформах.
File.symlink("testfile", "link2test") #=> 0
File.readlink("link2test") #=> "testfile"
static VALUE
rb_file_s_realdirpath(int argc, VALUE *argv, VALUE klass)
{
VALUE path, basedir;
rb_scan_args(argc, argv, "11", &path, &basedir);
return rb_realpath_internal(basedir, path, 0);
} Возвращает реальное (абсолютное) имя пути pathname в фактической файловой системе. Реальное имя пути не содержит символических ссылок или бесполезных точек.
Если задан dir_string, он используется в качестве базового каталога для интерпретации относительного имени пути вместо текущего каталога.
Последний компонент реального имени пути может отсутствовать.
static VALUE
rb_file_s_realpath(int argc, VALUE *argv, VALUE klass)
{
VALUE path, basedir;
rb_scan_args(argc, argv, "11", &path, &basedir);
return rb_realpath_internal(basedir, path, 1);
} Возвращает реальное (абсолютное) имя пути pathname в фактической файловой системе, не содержащее символических ссылок или бесполезных точек.
Если задан dir_string, он используется в качестве базового каталога для интерпретации относительного имени пути вместо текущего каталога.
Все компоненты имени пути должны существовать при вызове этого метода.
static VALUE
rb_file_s_rename(VALUE klass, VALUE from, VALUE to)
{
const char *src, *dst;
VALUE f, t;
FilePathValue(from);
FilePathValue(to);
f = rb_str_encode_ospath(from);
t = rb_str_encode_ospath(to);
src = StringValueCStr(f);
dst = StringValueCStr(t);
#if defined __CYGWIN__
errno = 0;
#endif
if (rename(src, dst) < 0) {
int e = errno;
#if defined DOSISH
switch (e) {
case EEXIST:
if (chmod(dst, 0666) == 0 &&
unlink(dst) == 0 &&
rename(src, dst) == 0)
return INT2FIX(0);
}
#endif
syserr_fail2(e, from, to);
}
return INT2FIX(0);
} Переименовывает данный файл в новое имя. Вызывает SystemCallError, если файл не может быть переименован.
File.rename("afile", "afile.bak") #=> 0
static VALUE
rb_file_sgid_p(VALUE obj, VALUE fname)
{
#ifdef S_ISGID
return check3rdbyte(fname, S_ISGID);
#else
return Qfalse;
#endif
} Возвращает true, если у указанного файла установлен бит setgid.
static VALUE
rb_file_suid_p(VALUE obj, VALUE fname)
{
#ifdef S_ISUID
return check3rdbyte(fname, S_ISUID);
#else
return Qfalse;
#endif
} Возвращает true, если у указанного файла установлен бит setuid.
static VALUE
rb_file_s_size(VALUE klass, VALUE fname)
{
struct stat st;
if (rb_stat(fname, &st) < 0) {
int e = errno;
FilePathValue(fname);
rb_syserr_fail_path(e, fname);
}
return OFFT2NUM(st.st_size);
} Возвращает размер file_name.
file_name может быть объектом IO.
static VALUE
rb_file_size_p(VALUE obj, VALUE fname)
{
struct stat st;
if (rb_stat(fname, &st) < 0) return Qnil;
if (st.st_size == 0) return Qnil;
return OFFT2NUM(st.st_size);
} Возвращает nil, если file_name не существует или имеет нулевой размер, размер файла в противном случае.
file_name может быть объектом IO.
static VALUE
rb_file_socket_p(VALUE obj, VALUE fname)
{
#ifndef S_ISSOCK
# ifdef _S_ISSOCK
# define S_ISSOCK(m) _S_ISSOCK(m)
# else
# ifdef _S_IFSOCK
# define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
# else
# ifdef S_IFSOCK
# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
# endif
# endif
# endif
#endif
#ifdef S_ISSOCK
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISSOCK(st.st_mode)) return Qtrue;
#endif
return Qfalse;
} Возвращает true, если указанный файл является сокетом.
file_name может быть объектом IO.
static VALUE
rb_file_s_split(VALUE klass, VALUE path)
{
FilePathStringValue(path); /* get rid of converting twice */
return rb_assoc_new(rb_file_s_dirname(Qnil, path), rb_file_s_basename(1,&path));
} Разделяет заданную строку на компонент каталога и файла и возвращает их в двумерном массиве. См. также File::dirname и File::basename.
File.split("/home/gumby/.profile") #=> ["/home/gumby", ".profile"]
static VALUE
rb_file_s_stat(VALUE klass, VALUE fname)
{
struct stat st;
FilePathValue(fname);
if (rb_stat(fname, &st) < 0) {
rb_sys_fail_path(fname);
}
return rb_stat_new(&st);
} Возвращает объект File::Stat для указанного файла (см. File::Stat).
File.stat("testfile").mtime #=> Tue Apr 08 12:58:04 CDT 2003
static VALUE
rb_file_sticky_p(VALUE obj, VALUE fname)
{
#ifdef S_ISVTX
return check3rdbyte(fname, S_ISVTX);
#else
return Qnil;
#endif
} Возвращает true, если у указанного файла установлен липкий бит.
static VALUE
rb_file_s_symlink(VALUE klass, VALUE from, VALUE to)
{
FilePathValue(from);
FilePathValue(to);
from = rb_str_encode_ospath(from);
to = rb_str_encode_ospath(to);
if (symlink(StringValueCStr(from), StringValueCStr(to)) < 0) {
sys_fail2(from, to);
}
return INT2FIX(0);
} Создает символическую ссылку с именем new_name для существующего файла old_name. Вызывает исключение NotImplemented на платформах, которые не поддерживают символические ссылки.
File.symlink("testfile", "link2test") #=> 0
static VALUE
rb_file_symlink_p(VALUE obj, VALUE fname)
{
#ifndef S_ISLNK
# ifdef _S_ISLNK
# define S_ISLNK(m) _S_ISLNK(m)
# else
# ifdef _S_IFLNK
# define S_ISLNK(m) (((m) & S_IFMT) == _S_IFLNK)
# else
# ifdef S_IFLNK
# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
# endif
# endif
# endif
#endif
#ifdef S_ISLNK
struct stat st;
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
if (lstat(StringValueCStr(fname), &st) < 0) return Qfalse;
if (S_ISLNK(st.st_mode)) return Qtrue;
#endif
return Qfalse;
} Возвращает true, если указанный файл является символической ссылкой.
static VALUE
rb_file_s_truncate(VALUE klass, VALUE path, VALUE len)
{
#ifdef HAVE_TRUNCATE
#define NUM2POS(n) NUM2OFFT(n)
off_t pos;
#else
#define NUM2POS(n) NUM2LONG(n)
long pos;
#endif
pos = NUM2POS(len);
FilePathValue(path);
path = rb_str_encode_ospath(path);
#ifdef HAVE_TRUNCATE
if (truncate(StringValueCStr(path), pos) < 0)
rb_sys_fail_path(path);
#else /* defined(HAVE_CHSIZE) */
{
int tmpfd;
if ((tmpfd = rb_cloexec_open(StringValueCStr(path), 0, 0)) < 0) {
rb_sys_fail_path(path);
}
rb_update_max_fd(tmpfd);
if (chsize(tmpfd, pos) < 0) {
int e = errno;
close(tmpfd);
rb_syserr_fail_path(e, path);
}
close(tmpfd);
}
#endif
return INT2FIX(0);
#undef NUM2POS
} Усекает файл file_name до размера не более integer байт. Не доступно на всех платформах.
f = File.new("out", "w")
f.write("1234567890") #=> 10
f.close #=> nil
File.truncate("out", 5) #=> 0
File.size("out") #=> 5
static VALUE
rb_file_s_umask(int argc, VALUE *argv)
{
int omask = 0;
if (argc == 0) {
omask = umask(0);
umask(omask);
}
else if (argc == 1) {
omask = umask(NUM2INT(argv[0]));
}
else {
rb_check_arity(argc, 0, 1);
}
return INT2FIX(omask);
} Возвращает текущее значение umask для данного процесса. Если необязательный аргумент задан, устанавливает umask в это значение и возвращает предыдущее значение. Значения umask вычитаются из стандартных разрешений, поэтому umask 0222 сделает файл доступным только для чтения для всех.
File.umask(0006) #=> 18 File.umask #=> 6
static VALUE
rb_file_s_unlink(VALUE klass, VALUE args)
{
long n;
n = apply2files(unlink_internal, args, 0);
return LONG2FIX(n);
} Удаляет указанные файлы, возвращая количество переданных имен. При возникновении ошибки выбрасывает исключение. См. также Dir::rmdir.
static VALUE
rb_file_s_utime(int argc, VALUE *argv)
{
VALUE rest;
struct utime_args args;
struct timespec tss[2], *tsp = NULL;
long n;
rb_scan_args(argc, argv, "2*", &args.atime, &args.mtime, &rest);
if (!NIL_P(args.atime) || !NIL_P(args.mtime)) {
tsp = tss;
tsp[0] = rb_time_timespec(args.atime);
if (args.atime == args.mtime)
tsp[1] = tsp[0];
else
tsp[1] = rb_time_timespec(args.mtime);
}
args.tsp = tsp;
n = apply2files(utime_internal, rest, &args);
return LONG2FIX(n);
} Устанавливает время доступа и изменения каждого указанного файла на значения первых двух аргументов. Возвращает количество имен файлов в списке аргументов.
static VALUE
rb_file_world_readable_p(VALUE obj, VALUE fname)
{
#ifdef S_IROTH
struct stat st;
if (rb_stat(fname, &st) < 0) return Qnil;
if ((st.st_mode & (S_IROTH)) == S_IROTH) {
return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
}
#endif
return Qnil;
} Если файл file_name доступен для других, возвращает целое число, представляющее биты разрешений файла file_name. В противном случае возвращает nil. Значение бит зависит от платформы; в системах Unix, см. stat(2).
file_name может быть объектом IO.
File.world_readable?("/etc/passwd") #=> 420
m = File.world_readable?("/etc/passwd")
sprintf("%o", m) #=> "644"
static VALUE
rb_file_world_writable_p(VALUE obj, VALUE fname)
{
#ifdef S_IWOTH
struct stat st;
if (rb_stat(fname, &st) < 0) return Qnil;
if ((st.st_mode & (S_IWOTH)) == S_IWOTH) {
return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
}
#endif
return Qnil;
} Если файл file_name доступен для записи другим, возвращает целое число, представляющее биты разрешений файла file_name. В противном случае возвращает nil. Значение бит зависит от платформы; в системах Unix, см. stat(2).
file_name может быть объектом IO.
File.world_writable?("/tmp") #=> 511
m = File.world_writable?("/tmp")
sprintf("%o", m) #=> "777"
static VALUE
rb_file_writable_p(VALUE obj, VALUE fname)
{
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
if (eaccess(StringValueCStr(fname), W_OK) < 0) return Qfalse;
return Qtrue;
} Возвращает true, если указанный файл доступен для записи для текущего пользователя и группы. См. eaccess(3).
static VALUE
rb_file_writable_real_p(VALUE obj, VALUE fname)
{
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
if (access(StringValueCStr(fname), W_OK) < 0) return Qfalse;
return Qtrue;
} Возвращает true, если указанный файл доступен для записи для реального пользователя и группы. См. access(3)
static VALUE
rb_file_zero_p(VALUE obj, VALUE fname)
{
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (st.st_size == 0) return Qtrue;
return Qfalse;
} Возвращает true, если указанный файл существует и имеет размер 0.
file_name может быть объектом IO объекта.
Методы экземпляра общедоступного класса
static VALUE
rb_file_atime(VALUE obj)
{
rb_io_t *fptr;
struct stat st;
GetOpenFile(obj, fptr);
if (fstat(fptr->fd, &st) == -1) {
rb_sys_fail_path(fptr->pathv);
}
return stat_atime(&st);
} Возвращает время последнего доступа (объект Time)
for <i>file</i>, or epoch if <i>file</i> has not been accessed.
File.new("testfile").atime #=> Wed Dec 31 18:00:00 CST 1969 static VALUE
rb_file_birthtime(VALUE obj)
{
rb_io_t *fptr;
struct stat st;
GetOpenFile(obj, fptr);
if (fstat(fptr->fd, &st) == -1) {
rb_sys_fail_path(fptr->pathv);
}
return stat_birthtime(&st);
} Возвращает время создания файла.
File.new("testfile").birthtime #=> Wed Apr 09 08:53:14 CDT 2003
Если платформа не поддерживает время создания, генерирует исключение NotImplementedError.
static VALUE
rb_file_chmod(VALUE obj, VALUE vmode)
{
rb_io_t *fptr;
int mode;
#if !defined HAVE_FCHMOD || !HAVE_FCHMOD
VALUE path;
#endif
mode = NUM2INT(vmode);
GetOpenFile(obj, fptr);
#ifdef HAVE_FCHMOD
if (fchmod(fptr->fd, mode) == -1) {
if (HAVE_FCHMOD || errno != ENOSYS)
rb_sys_fail_path(fptr->pathv);
}
else {
if (!HAVE_FCHMOD) return INT2FIX(0);
}
#endif
#if !defined HAVE_FCHMOD || !HAVE_FCHMOD
if (NIL_P(fptr->pathv)) return Qnil;
path = rb_str_encode_ospath(fptr->pathv);
if (chmod(RSTRING_PTR(path), mode) == -1)
rb_sys_fail_path(fptr->pathv);
#endif
return INT2FIX(0);
} Изменяет биты разрешений файла на битовую схему, представленную mode_int. Реальный эффект зависит от платформы; в системах Unix см. chmod(2) для подробностей. Следует за символическими ссылками. Также см. File#lchmod.
f = File.new("out", "w");
f.chmod(0644) #=> 0
static VALUE
rb_file_chown(VALUE obj, VALUE owner, VALUE group)
{
rb_io_t *fptr;
rb_uid_t o;
rb_gid_t g;
#ifndef HAVE_FCHOWN
VALUE path;
#endif
o = to_uid(owner);
g = to_gid(group);
GetOpenFile(obj, fptr);
#ifndef HAVE_FCHOWN
if (NIL_P(fptr->pathv)) return Qnil;
path = rb_str_encode_ospath(fptr->pathv);
if (chown(RSTRING_PTR(path), o, g) == -1)
rb_sys_fail_path(fptr->pathv);
#else
if (fchown(fptr->fd, o, g) == -1)
rb_sys_fail_path(fptr->pathv);
#endif
return INT2FIX(0);
} Изменяет владельца и группу файла на заданные числовые идентификаторы владельца и группы. Только процесс с привилегиями суперпользователя может изменить владельца файла. Текущий владелец файла может изменить группу файла на любую группу, к которой принадлежит владелец. Идентификатор владельца или группы nil или -1 игнорируется. Следует за символическими ссылками. Также см. File#lchown.
File.new("testfile").chown(502, 1000)
static VALUE
rb_file_ctime(VALUE obj)
{
rb_io_t *fptr;
struct stat st;
GetOpenFile(obj, fptr);
if (fstat(fptr->fd, &st) == -1) {
rb_sys_fail_path(fptr->pathv);
}
return stat_ctime(&st);
} Возвращает время изменения файла (то есть время изменения метаданных о файле, а не самого файла).
Обратите внимание, что в Windows (NTFS) возвращается время создания (время рождения).
File.new("testfile").ctime #=> Wed Apr 09 08:53:14 CDT 2003
static VALUE
rb_file_flock(VALUE obj, VALUE operation)
{
rb_io_t *fptr;
int op[2], op1;
struct timeval time;
op[1] = op1 = NUM2INT(operation);
GetOpenFile(obj, fptr);
op[0] = fptr->fd;
if (fptr->mode & FMODE_WRITABLE) {
rb_io_flush_raw(obj, 0);
}
while ((int)rb_thread_io_blocking_region(rb_thread_flock, op, fptr->fd) < 0) {
int e = errno;
switch (e) {
case EAGAIN:
case EACCES:
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
case EWOULDBLOCK:
#endif
if (op1 & LOCK_NB) return Qfalse;
time.tv_sec = 0;
time.tv_usec = 100 * 1000; /* 0.1 sec */
rb_thread_wait_for(time);
rb_io_check_closed(fptr);
continue;
case EINTR:
#if defined(ERESTART)
case ERESTART:
#endif
break;
default:
rb_syserr_fail_path(e, fptr->pathv);
}
}
return INT2FIX(0);
} Заблокировать или разблокировать файл в соответствии с locking_constant (логическое ИЛИ значений в таблице ниже). Возвращает false, если File::LOCK_NB указано, и операция в противном случае была бы заблокирована. Не доступно на всех платформах.
Константы блокировки (в классе File):
LOCK_EX | Exclusive lock. Only one process may hold an
| exclusive lock for a given file at a time.
----------+------------------------------------------------
LOCK_NB | Don't block when locking. May be combined
| with other lock options using logical or.
----------+------------------------------------------------
LOCK_SH | Shared lock. Multiple processes may each hold a
| shared lock for a given file at the same time.
----------+------------------------------------------------
LOCK_UN | Unlock. Пример:
# update a counter using write lock
# don't use "w" because it truncates the file before lock.
File.open("counter", File::RDWR|File::CREAT, 0644) {|f|
f.flock(File::LOCK_EX)
value = f.read.to_i + 1
f.rewind
f.write("#{value}\n")
f.flush
f.truncate(f.pos)
}
# read the counter using read lock
File.open("counter", "r") {|f|
f.flock(File::LOCK_SH)
p f.read
}
static VALUE
rb_file_lstat(VALUE obj)
{
#ifdef HAVE_LSTAT
rb_io_t *fptr;
struct stat st;
VALUE path;
GetOpenFile(obj, fptr);
if (NIL_P(fptr->pathv)) return Qnil;
path = rb_str_encode_ospath(fptr->pathv);
if (lstat(RSTRING_PTR(path), &st) == -1) {
rb_sys_fail_path(fptr->pathv);
}
return rb_stat_new(&st);
#else
return rb_io_stat(obj);
#endif
} Аналогично IO#stat, но не следует за последней символической ссылкой. Вместо этого сообщает о самой ссылке.
File.symlink("testfile", "link2test") #=> 0
File.stat("testfile").size #=> 66
f = File.new("link2test")
f.lstat.size #=> 8
f.stat.size #=> 66
static VALUE
rb_file_mtime(VALUE obj)
{
rb_io_t *fptr;
struct stat st;
GetOpenFile(obj, fptr);
if (fstat(fptr->fd, &st) == -1) {
rb_sys_fail_path(fptr->pathv);
}
return stat_mtime(&st);
} Возвращает время изменения файла.
File.new("testfile").mtime #=> Wed Apr 09 08:53:14 CDT 2003
static VALUE
rb_file_path(VALUE obj)
{
rb_io_t *fptr;
fptr = RFILE(rb_io_taint_check(obj))->fptr;
rb_io_check_initialized(fptr);
if (NIL_P(fptr->pathv)) return Qnil;
return rb_obj_taint(rb_str_dup(fptr->pathv));
} Возвращает путь к файлу, используемый для создания файла, как строку. Имя не нормализуется.
File.new("testfile").path #=> "testfile"
File.new("/tmp/../tmp/xxx", "w").path #=> "/tmp/../tmp/xxx"
static VALUE
rb_file_size(VALUE obj)
{
rb_io_t *fptr;
struct stat st;
GetOpenFile(obj, fptr);
if (fptr->mode & FMODE_WRITABLE) {
rb_io_flush_raw(obj, 0);
}
if (fstat(fptr->fd, &st) == -1) {
rb_sys_fail_path(fptr->pathv);
}
return OFFT2NUM(st.st_size);
} Возвращает размер файла в байтах.
File.new("testfile").size #=> 66
static VALUE
rb_file_path(VALUE obj)
{
rb_io_t *fptr;
fptr = RFILE(rb_io_taint_check(obj))->fptr;
rb_io_check_initialized(fptr);
if (NIL_P(fptr->pathv)) return Qnil;
return rb_obj_taint(rb_str_dup(fptr->pathv));
} Возвращает путь к файлу, используемый для создания файла, как строку. Имя не нормализуется.
File.new("testfile").path #=> "testfile"
File.new("/tmp/../tmp/xxx", "w").path #=> "/tmp/../tmp/xxx"
static VALUE
rb_file_truncate(VALUE obj, VALUE len)
{
rb_io_t *fptr;
#if defined(HAVE_FTRUNCATE)
#define NUM2POS(n) NUM2OFFT(n)
off_t pos;
#else
#define NUM2POS(n) NUM2LONG(n)
long pos;
#endif
pos = NUM2POS(len);
GetOpenFile(obj, fptr);
if (!(fptr->mode & FMODE_WRITABLE)) {
rb_raise(rb_eIOError, "not opened for writing");
}
rb_io_flush_raw(obj, 0);
#ifdef HAVE_FTRUNCATE
if (ftruncate(fptr->fd, pos) < 0)
rb_sys_fail_path(fptr->pathv);
#else /* defined(HAVE_CHSIZE) */
if (chsize(fptr->fd, pos) < 0)
rb_sys_fail_path(fptr->pathv);
#endif
return INT2FIX(0);
#undef NUM2POS
} Усекает файл до максимум целого байтов. Файл должен быть открыт для записи. Не доступно на всех платформах.
f = File.new("out", "w")
f.syswrite("1234567890") #=> 10
f.truncate(5) #=> 0
f.close() #=> nil
File.size("out") #=> 5
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.