класс Pathname
Pathname представляет имя файла или каталога в файловой системе, но не сам файл.
Путь зависит от операционной системы: Unix, Windows и т. д. Эта библиотека работает с именами путей локальной ОС, однако имена путей, отличные от Unix, поддерживаются экспериментально.
Имя пути (Pathname) может быть относительным или абсолютным. Только при попытке обратиться к файлу важно, существует ли файл или нет.
Имя пути (Pathname) неизменяемо. У него нет методов для деструктивного обновления.
Цель этого класса — манипулировать информацией о путях файлов более удобным способом, чем стандартная реализация Ruby. Примеры ниже демонстрируют разницу.
Все функциональные возможности из File, FileTest, и некоторые из Dir и FileUtils включены, что вполне предсказуемо. По существу, это фронт для всех этих и других возможностей.
Примеры
Пример 1: Использование Pathname
require 'pathname'
pn = Pathname.new("/usr/bin/ruby")
size = pn.size # 27662
isdir = pn.directory? # false
dir = pn.dirname # Pathname:/usr/bin
base = pn.basename # Pathname:ruby
dir, base = pn.split # [Pathname:/usr/bin, Pathname:ruby]
data = pn.read
pn.open { |f| _ }
pn.each_line { |line| _ }
Пример 2: Использование стандартного Ruby
pn = "/usr/bin/ruby"
size = File.size(pn) # 27662
isdir = File.directory?(pn) # false
dir = File.dirname(pn) # "/usr/bin"
base = File.basename(pn) # "ruby"
dir, base = File.split(pn) # ["/usr/bin", "ruby"]
data = File.read(pn)
File.open(pn) { |f| _ }
File.foreach(pn) { |line| _ }
Пример 3: Специальные возможности
p1 = Pathname.new("/usr/lib") # Pathname:/usr/lib
p2 = p1 + "ruby/1.8" # Pathname:/usr/lib/ruby/1.8
p3 = p1.parent # Pathname:/usr
p4 = p2.relative_path_from(p3) # Pathname:lib/ruby/1.8
pwd = Pathname.pwd # Pathname:/home/gavin
pwd.absolute? # true
p5 = Pathname.new "." # Pathname:.
p5 = p5 + "music/../articles" # Pathname:music/../articles
p5.cleanpath # Pathname:articles
p5.realpath # Pathname:/home/gavin/articles
p5.children # [Pathname:/home/gavin/articles/linux, ...]
Детализация функциональности
Основные методы
Эти методы фактически манипулируют строкой (String), поскольку именно таковым является путь. Ни один из них не обращается к файловой системе, за исключением mountpoint?, children, each_child, realdirpath и realpath.
-
+
File методы проверки статуса
Эти методы — фронт для FileTest:
File свойства и методы манипулирования
Эти методы — фронт для File:
-
chown(владелец, группа) -
lchown(владелец, группа) -
fnmatch(шаблон, *аргументы) -
fnmatch?(шаблон, *аргументы) -
open(*аргументы, &блок) -
utime(время_доступа, время_изменения)
Методы каталогов
Эти методы — фронт для Dir:
-
each_entry(&блок)
IO
Эти методы — фронт для IO:
-
each_line(*аргументы, &блок)
Утилиты
Эти методы — смесь из Find, FileUtils и других:
Method документация
Как видно из предыдущего раздела, большинство методов в Pathname являются фронт-энд-методами. Документация к таким методам обычно просто ссылается, например, на «См. FileTest.writable?», поскольку вы должны быть знакомы с исходным методом и его документацией (например, через ri), которая содержит более подробную информацию. В некоторых случаях следует краткое описание.
Методы публичного класса
static VALUE
path_s_glob(int argc, VALUE *argv, VALUE klass)
{
VALUE args[3];
int n;
n = rb_scan_args(argc, argv, "12", &args[0], &args[1], &args[2]);
if (rb_block_given_p()) {
return rb_block_call_kw(rb_cDir, id_glob, n, args, s_glob_i, klass, RB_PASS_CALLED_KEYWORDS);
}
else {
VALUE ary;
long i;
ary = rb_funcallv_kw(rb_cDir, id_glob, n, args, RB_PASS_CALLED_KEYWORDS);
ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
for (i = 0; i < RARRAY_LEN(ary); i++) {
VALUE elt = RARRAY_AREF(ary, i);
elt = rb_class_new_instance(1, &elt, klass);
rb_ary_store(ary, i, elt);
}
return ary;
}
} Возвращает или итерирует объекты Pathname.
Pathname.glob("lib/i*.rb")
#=> [#<Pathname:lib/ipaddr.rb>, #<Pathname:lib/irb.rb>]
См. Dir.glob.
static VALUE
path_initialize(VALUE self, VALUE arg)
{
VALUE str;
if (RB_TYPE_P(arg, T_STRING)) {
str = arg;
}
else {
str = rb_check_funcall(arg, id_to_path, 0, NULL);
if (str == Qundef)
str = arg;
StringValue(str);
}
if (memchr(RSTRING_PTR(str), '\0', RSTRING_LEN(str)))
rb_raise(rb_eArgError, "pathname contains null byte");
str = rb_obj_dup(str);
set_strpath(self, str);
return self;
} Создаёт объект Pathname из заданного String (или объекта, подобного строке). Если path содержит нулевой символ (\0), генерируется исключение ArgumentError.
Публичные методы экземпляра
# File ext/pathname/lib/pathname.rb, line 352 def +(other) other = Pathname.new(other) unless Pathname === other Pathname.new(plus(@path, other.to_s)) end
Добавляет фрагмент пути к self для создания нового объекта Pathname.
p1 = Pathname.new("/usr") # Pathname:/usr
p2 = p1 + "bin/ruby" # Pathname:/usr/bin/ruby
p3 = p1 + "/etc/passwd" # Pathname:/etc/passwd
# / is aliased to +.
p4 = p1 / "bin/ruby" # Pathname:/usr/bin/ruby
p5 = p1 / "/etc/passwd" # Pathname:/etc/passwd
Этот метод не обращается к файловой системе; это чистое манипулирование строками.
static VALUE
path_cmp(VALUE self, VALUE other)
{
VALUE s1, s2;
char *p1, *p2;
char *e1, *e2;
if (!rb_obj_is_kind_of(other, rb_cPathname))
return Qnil;
s1 = get_strpath(self);
s2 = get_strpath(other);
p1 = RSTRING_PTR(s1);
p2 = RSTRING_PTR(s2);
e1 = p1 + RSTRING_LEN(s1);
e2 = p2 + RSTRING_LEN(s2);
while (p1 < e1 && p2 < e2) {
int c1, c2;
c1 = (unsigned char)*p1++;
c2 = (unsigned char)*p2++;
if (c1 == '/') c1 = '\0';
if (c2 == '/') c2 = '\0';
if (c1 != c2) {
if (c1 < c2)
return INT2FIX(-1);
else
return INT2FIX(1);
}
}
if (p1 < e1)
return INT2FIX(1);
if (p2 < e2)
return INT2FIX(-1);
return INT2FIX(0);
} Предоставляет оператор сравнения с учетом регистра для имен путей.
Pathname.new('/usr') <=> Pathname.new('/usr/bin')
#=> -1
Pathname.new('/usr/bin') <=> Pathname.new('/usr/bin')
#=> 0
Pathname.new('/usr/bin') <=> Pathname.new('/USR/BIN')
#=> 1
Он вернет -1, 0 или 1 в зависимости от значения левого аргумента относительно правого аргумента. Или он вернет nil, если аргументы не могут быть сравнены.
static VALUE
path_eq(VALUE self, VALUE other)
{
if (!rb_obj_is_kind_of(other, rb_cPathname))
return Qfalse;
return rb_str_equal(get_strpath(self), get_strpath(other));
} Сравнивает это имя пути с other. Сравнение основано на строках. Имейте в виду, что два разных пути (foo.txt и ./foo.txt) могут ссылаться на один и тот же файл.
Сравнивает это имя пути с other. Сравнение основано на строках. Имейте в виду, что два разных пути (foo.txt и ./foo.txt) могут ссылаться на один и тот же файл.
# File ext/pathname/lib/pathname.rb, line 231 def absolute? ABSOLUTE_PATH.match? @path end
Метод-предикат для проверки, является ли путь абсолютным.
Возвращает true, если имя пути начинается с косой черты.
p = Pathname.new('/im/sure')
p.absolute?
#=> true
p = Pathname.new('not/so/sure')
p.absolute?
#=> false
# File ext/pathname/lib/pathname.rb, line 328
def ascend
return to_enum(__method__) unless block_given?
path = @path
yield self
while r = chop_basename(path)
path, = r
break if path.empty?
yield self.class.new(del_trailing_separator(path))
end
end Перебирает и возвращает новый объект Pathname для каждого элемента в заданном пути в восходящем порядке.
Pathname.new('/path/to/some/file.rb').ascend {|v| p v}
#<Pathname:/path/to/some/file.rb>
#<Pathname:/path/to/some>
#<Pathname:/path/to>
#<Pathname:/path>
#<Pathname:/>
Pathname.new('path/to/some/file.rb').ascend {|v| p v}
#<Pathname:path/to/some/file.rb>
#<Pathname:path/to/some>
#<Pathname:path/to>
#<Pathname:path>
Возвращает Enumerator, если блок не был задан.
enum = Pathname.new("/usr/bin/ruby").ascend
# ... do stuff ...
enum.each { |e| ... }
# yields Pathnames /usr/bin/ruby, /usr/bin, /usr, and /. Он не обращается к файловой системе.
static VALUE
path_atime(VALUE self)
{
return rb_funcall(rb_cFile, id_atime, 1, get_strpath(self));
} Возвращает время последнего доступа к файлу.
См. File.atime.
static VALUE
path_basename(int argc, VALUE *argv, VALUE self)
{
VALUE str = get_strpath(self);
VALUE fext;
if (rb_scan_args(argc, argv, "01", &fext) == 0)
str = rb_funcall(rb_cFile, id_basename, 1, str);
else
str = rb_funcall(rb_cFile, id_basename, 2, str, fext);
return rb_class_new_instance(1, &str, rb_obj_class(self));
} Возвращает последний компонент пути.
См. File.basename.
static VALUE
path_binread(int argc, VALUE *argv, VALUE self)
{
VALUE args[3];
int n;
args[0] = get_strpath(self);
n = rb_scan_args(argc, argv, "02", &args[1], &args[2]);
return rb_funcallv(rb_cFile, id_binread, 1+n, args);
} Возвращает все байты из файла или первые N, если указано.
См. File.binread.
static VALUE
path_binwrite(int argc, VALUE *argv, VALUE self)
{
VALUE args[4];
int n;
args[0] = get_strpath(self);
n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
return rb_funcallv_kw(rb_cFile, id_binwrite, 1+n, args, RB_PASS_CALLED_KEYWORDS);
} Записывает contents в файл, открывая его в бинарном режиме.
См. File.binwrite.
static VALUE
path_birthtime(VALUE self)
{
return rb_funcall(rb_cFile, id_birthtime, 1, get_strpath(self));
} Возвращает время создания файла. Если платформа не имеет времени создания, вызывает NotImplementedError.
См. File.birthtime.
static VALUE
path_blockdev_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_blockdev_p, 1, get_strpath(self));
} См. FileTest.blockdev?.
static VALUE
path_chardev_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_chardev_p, 1, get_strpath(self));
} См. FileTest.chardev?.
# File ext/pathname/lib/pathname.rb, line 443
def children(with_directory=true)
with_directory = false if @path == '.'
result = []
Dir.foreach(@path) {|e|
next if e == '.' || e == '..'
if with_directory
result << self.class.new(File.join(@path, e))
else
result << self.class.new(e)
end
}
result
end Возвращает дочерние элементы каталога (файлы и подкаталоги, не рекурсивно) в виде массива объектов Pathname.
По умолчанию возвращаемые имена путей будут содержать достаточно информации для доступа к файлам. Если вы установите with_directory в false, то возвращаемые имена путей будут содержать только имя файла.
Например:
pn = Pathname("/usr/lib/ruby/1.8")
pn.children
# -> [ Pathname:/usr/lib/ruby/1.8/English.rb,
Pathname:/usr/lib/ruby/1.8/Env.rb,
Pathname:/usr/lib/ruby/1.8/abbrev.rb, ... ]
pn.children(false)
# -> [ Pathname:English.rb, Pathname:Env.rb, Pathname:abbrev.rb, ... ] Обратите внимание, что результаты никогда не содержат элементов . и .. в каталоге, поскольку они не являются дочерними.
static VALUE
path_chmod(VALUE self, VALUE mode)
{
return rb_funcall(rb_cFile, id_chmod, 2, mode, get_strpath(self));
} Изменяет права доступа к файлу.
См. File.chmod.
static VALUE
path_chown(VALUE self, VALUE owner, VALUE group)
{
return rb_funcall(rb_cFile, id_chown, 3, owner, group, get_strpath(self));
} Изменяет владельца и группу файла.
См. File.chown.
# File ext/pathname/lib/pathname.rb, line 92
def cleanpath(consider_symlink=false)
if consider_symlink
cleanpath_conservative
else
cleanpath_aggressive
end
end Возвращает очищенное имя пути self с удаленными последовательными слэшами и бесполезными точками. Файловая система не используется.
Если consider_symlink равно true, то используется более консервативный алгоритм, чтобы избежать нарушения символических ссылок. Это может сохранить больше записей .., чем абсолютно необходимо, но без доступа к файловой системе этого избежать нельзя.
См. Pathname#realpath.
static VALUE
path_ctime(VALUE self)
{
return rb_funcall(rb_cFile, id_ctime, 1, get_strpath(self));
} Возвращает время последнего изменения, используя информацию о каталоге, а не сам файл.
См. File.ctime.
Удаляет файл или каталог, используя File.unlink, если self является файлом, или Dir.unlink по мере необходимости.
# File ext/pathname/lib/pathname.rb, line 295
def descend
return to_enum(__method__) unless block_given?
vs = []
ascend {|v| vs << v }
vs.reverse_each {|v| yield v }
nil
end Перебирает и возвращает новый объект Pathname для каждого элемента в заданном пути в порядке убывания.
Pathname.new('/path/to/some/file.rb').descend {|v| p v}
#<Pathname:/>
#<Pathname:/path>
#<Pathname:/path/to>
#<Pathname:/path/to/some>
#<Pathname:/path/to/some/file.rb>
Pathname.new('path/to/some/file.rb').descend {|v| p v}
#<Pathname:path>
#<Pathname:path/to>
#<Pathname:path/to/some>
#<Pathname:path/to/some/file.rb>
Возвращает Enumerator, если блок не был задан.
enum = Pathname.new("/usr/bin/ruby").descend
# ... do stuff ...
enum.each { |e| ... }
# yields Pathnames /, /usr, /usr/bin, and /usr/bin/ruby. Не обращается к файловой системе.
static VALUE
path_directory_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_directory_p, 1, get_strpath(self));
} См. FileTest.directory?.
static VALUE
path_dirname(VALUE self)
{
VALUE str = get_strpath(self);
str = rb_funcall(rb_cFile, id_dirname, 1, str);
return rb_class_new_instance(1, &str, rb_obj_class(self));
} Возвращает все компоненты пути, кроме последнего.
См. File.dirname.
# File ext/pathname/lib/pathname.rb, line 493 def each_child(with_directory=true, &b) children(with_directory).each(&b) end
Перебирает дочерние элементы каталога (файлы и подкаталоги, не рекурсивно).
Возвращает объект Pathname для каждого дочернего элемента.
По умолчанию возвращаемые пути содержат достаточную информацию для доступа к файлам.
Если вы установите with_directory в false, то возвращаемые пути будут содержать только имя файла.
Pathname("/usr/local").each_child {|f| p f }
#=> #<Pathname:/usr/local/share>
# #<Pathname:/usr/local/bin>
# #<Pathname:/usr/local/games>
# #<Pathname:/usr/local/lib>
# #<Pathname:/usr/local/include>
# #<Pathname:/usr/local/sbin>
# #<Pathname:/usr/local/src>
# #<Pathname:/usr/local/man>
Pathname("/usr/local").each_child(false) {|f| p f }
#=> #<Pathname:share>
# #<Pathname:bin>
# #<Pathname:games>
# #<Pathname:lib>
# #<Pathname:include>
# #<Pathname:sbin>
# #<Pathname:src>
# #<Pathname:man>
Обратите внимание, что результаты никогда не содержат записи . и .. в каталоге, так как они не являются дочерними элементами.
static VALUE
path_each_entry(VALUE self)
{
VALUE args[1];
args[0] = get_strpath(self);
return rb_block_call(rb_cDir, id_foreach, 1, args, each_entry_i, rb_obj_class(self));
} Перебирает записи (файлы и подкаталоги) в каталоге, возвращая объект Pathname для каждой записи.
# File ext/pathname/lib/pathname.rb, line 263
def each_filename # :yield: filename
return to_enum(__method__) unless block_given?
_, names = split_names(@path)
names.each {|filename| yield filename }
nil
end Перебирает каждый компонент пути.
Pathname.new("/usr/bin/ruby").each_filename {|filename| ... }
# yields "usr", "bin", and "ruby". Возвращает Enumerator, если блок не был задан.
enum = Pathname.new("/usr/bin/ruby").each_filename
# ... do stuff ...
enum.each { |e| ... }
# yields "usr", "bin", and "ruby". static VALUE
path_each_line(int argc, VALUE *argv, VALUE self)
{
VALUE args[4];
int n;
args[0] = get_strpath(self);
n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
if (rb_block_given_p()) {
return rb_block_call_kw(rb_cFile, id_foreach, 1+n, args, 0, 0, RB_PASS_CALLED_KEYWORDS);
}
else {
return rb_funcallv_kw(rb_cFile, id_foreach, 1+n, args, RB_PASS_CALLED_KEYWORDS);
}
} Перебирает каждую строку в файле и возвращает объект String для каждой.
static VALUE
path_empty_p(VALUE self)
{
VALUE path = get_strpath(self);
if (RTEST(rb_funcall(rb_mFileTest, id_directory_p, 1, path)))
return rb_funcall(rb_cDir, id_empty_p, 1, path);
else
return rb_funcall(rb_mFileTest, id_empty_p, 1, path);
} Проверяет, пуст ли файл.
См. Dir#empty? и FileTest.empty?.
static VALUE
path_entries(VALUE self)
{
VALUE klass, str, ary;
long i;
klass = rb_obj_class(self);
str = get_strpath(self);
ary = rb_funcall(rb_cDir, id_entries, 1, str);
ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
for (i = 0; i < RARRAY_LEN(ary); i++) {
VALUE elt = RARRAY_AREF(ary, i);
elt = rb_class_new_instance(1, &elt, klass);
rb_ary_store(ary, i, elt);
}
return ary;
} Возвращает записи (файлы и подкаталоги) в каталоге, каждый как объект Pathname.
Результаты содержат только имена в каталоге без каких-либо последующих слешей или рекурсивного поиска.
pp Pathname.new('/usr/local').entries
#=> [#<Pathname:share>,
# #<Pathname:lib>,
# #<Pathname:..>,
# #<Pathname:include>,
# #<Pathname:etc>,
# #<Pathname:bin>,
# #<Pathname:man>,
# #<Pathname:games>,
# #<Pathname:.>,
# #<Pathname:sbin>,
# #<Pathname:src>]
Результат может содержать текущий каталог #<Pathname:.> и родительский каталог #<Pathname:..>.
Если вам не нужны . и .. и нужны каталоги, обратите внимание на Pathname#children.
Сравнивает этот путь с other. Сравнение выполняется на основе строк. Имейте в виду, что два разных пути (foo.txt и ./foo.txt) могут ссылаться на один и тот же файл.
static VALUE
path_executable_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_executable_p, 1, get_strpath(self));
} См. FileTest.executable?.
static VALUE
path_executable_real_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_executable_real_p, 1, get_strpath(self));
} static VALUE
path_exist_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_exist_p, 1, get_strpath(self));
} См. FileTest.exist?.
static VALUE
path_expand_path(int argc, VALUE *argv, VALUE self)
{
VALUE str = get_strpath(self);
VALUE dname;
if (rb_scan_args(argc, argv, "01", &dname) == 0)
str = rb_funcall(rb_cFile, id_expand_path, 1, str);
else
str = rb_funcall(rb_cFile, id_expand_path, 2, str, dname);
return rb_class_new_instance(1, &str, rb_obj_class(self));
} Возвращает абсолютный путь к файлу.
См. File.expand_path.
static VALUE
path_extname(VALUE self)
{
VALUE str = get_strpath(self);
return rb_funcall(rb_cFile, id_extname, 1, str);
} Возвращает расширение файла.
См. File.extname.
static VALUE
path_file_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_file_p, 1, get_strpath(self));
} См. FileTest.file?.
# File ext/pathname/lib/pathname.rb, line 565
def find(ignore_error: true) # :yield: pathname
return to_enum(__method__, ignore_error: ignore_error) unless block_given?
require 'find'
if @path == '.'
Find.find(@path, ignore_error: ignore_error) {|f| yield self.class.new(f.sub(%r{\A\./}, '')) }
else
Find.find(@path, ignore_error: ignore_error) {|f| yield self.class.new(f) }
end
end Перебирает древовидную структуру каталогов в порядке глубины, возвращая Pathname для каждого файла в каталоге.
Возвращает Enumerator, если блок не задан.
Так как он реализован модулем стандартной библиотеки Find, Find.prune может быть использован для управления обходом.
Если self равно ., возвращаемые пути начинаются с имени файла в текущем каталоге, а не ./.
См. Find.find
static VALUE
path_fnmatch(int argc, VALUE *argv, VALUE self)
{
VALUE str = get_strpath(self);
VALUE pattern, flags;
if (rb_scan_args(argc, argv, "11", &pattern, &flags) == 1)
return rb_funcall(rb_cFile, id_fnmatch, 2, pattern, str);
else
return rb_funcall(rb_cFile, id_fnmatch, 3, pattern, str, flags);
} Возвращает true если получатель соответствует заданному шаблону.
См. File.fnmatch.
Возвращает true если получатель соответствует заданному шаблону.
См. File.fnmatch.
static VALUE
path_freeze(VALUE self)
{
rb_call_super(0, 0);
rb_str_freeze(get_strpath(self));
return self;
} Замораживает этот Pathname.
См. Object.freeze.
static VALUE
path_ftype(VALUE self)
{
return rb_funcall(rb_cFile, id_ftype, 1, get_strpath(self));
} Возвращает «тип» файла («файл», «каталог» и т.д.).
См. File.ftype.
static VALUE
path_glob(int argc, VALUE *argv, VALUE self)
{
VALUE args[3];
int n;
n = rb_scan_args(argc, argv, "11", &args[0], &args[1]);
if (n == 1)
args[1] = INT2FIX(0);
args[2] = rb_hash_new();
rb_hash_aset(args[2], ID2SYM(id_base), get_strpath(self));
n = 3;
if (rb_block_given_p()) {
return rb_block_call_kw(rb_cDir, id_glob, n, args, glob_i, self, RB_PASS_KEYWORDS);
}
else {
VALUE ary;
long i;
ary = rb_funcallv_kw(rb_cDir, id_glob, n, args, RB_PASS_KEYWORDS);
ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
for (i = 0; i < RARRAY_LEN(ary); i++) {
VALUE elt = RARRAY_AREF(ary, i);
elt = rb_funcall(self, '+', 1, elt);
rb_ary_store(ary, i, elt);
}
return ary;
}
} Возвращает или выдает объекты Pathname.
Pathname("ruby-2.4.2").glob("R*.md")
#=> [#<Pathname:ruby-2.4.2/README.md>, #<Pathname:ruby-2.4.2/README.ja.md>]
См. Dir.glob. Этот метод использует аргумент ключевого слова base из Dir.glob.
static VALUE
path_grpowned_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_grpowned_p, 1, get_strpath(self));
} См. FileTest.grpowned?.
# File ext/pathname/lib/pathname.rb, line 410
def join(*args)
return self if args.empty?
result = args.pop
result = Pathname.new(result) unless Pathname === result
return result if result.absolute?
args.reverse_each {|arg|
arg = Pathname.new(arg) unless Pathname === arg
result = arg + result
return result if result.absolute?
}
self + result
end Объединяет заданные пути в self для создания нового объекта Pathname.
path0 = Pathname.new("/usr") # Pathname:/usr
path0 = path0.join("bin/ruby") # Pathname:/usr/bin/ruby
# is the same as
path1 = Pathname.new("/usr") + "bin/ruby" # Pathname:/usr/bin/ruby
path0 == path1
#=> true
static VALUE
path_lchmod(VALUE self, VALUE mode)
{
return rb_funcall(rb_cFile, id_lchmod, 2, mode, get_strpath(self));
} То же, что и Pathname.chmod, но не следует символическим ссылкам.
См. File.lchmod.
static VALUE
path_lchown(VALUE self, VALUE owner, VALUE group)
{
return rb_funcall(rb_cFile, id_lchown, 3, owner, group, get_strpath(self));
} То же, что и Pathname.chown, но не следует символическим ссылкам.
См. File.lchown.
static VALUE
path_lstat(VALUE self)
{
return rb_funcall(rb_cFile, id_lstat, 1, get_strpath(self));
} См. File.lstat.
static VALUE
path_make_link(VALUE self, VALUE old)
{
return rb_funcall(rb_cFile, id_link, 2, old, get_strpath(self));
} Создает жесткую ссылку в pathname.
См. File.link.
static VALUE
path_make_symlink(VALUE self, VALUE old)
{
return rb_funcall(rb_cFile, id_symlink, 2, old, get_strpath(self));
} Создает символическую ссылку.
См. File.symlink.
static VALUE
path_mkdir(int argc, VALUE *argv, VALUE self)
{
VALUE str = get_strpath(self);
VALUE vmode;
if (rb_scan_args(argc, argv, "01", &vmode) == 0)
return rb_funcall(rb_cDir, id_mkdir, 1, str);
else
return rb_funcall(rb_cDir, id_mkdir, 2, str, vmode);
} Создает указанный каталог.
См. Dir.mkdir.
# File ext/pathname/lib/pathname.rb, line 584 def mkpath(mode: nil) FileUtils.mkpath(@path, mode: mode) nil end
Создает полный путь, включая все промежуточные каталоги, которые еще не существуют.
# File ext/pathname/lib/pathname.rb, line 199
def mountpoint?
begin
stat1 = self.lstat
stat2 = self.parent.lstat
stat1.dev != stat2.dev || stat1.ino == stat2.ino
rescue Errno::ENOENT
false
end
end Возвращает true, если self указывает на точку монтирования.
static VALUE
path_mtime(VALUE self)
{
return rb_funcall(rb_cFile, id_mtime, 1, get_strpath(self));
} Возвращает время последнего изменения файла.
См. File.mtime.
static VALUE
path_open(int argc, VALUE *argv, VALUE self)
{
VALUE args[4];
int n;
args[0] = get_strpath(self);
n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
if (rb_block_given_p()) {
return rb_block_call_kw(rb_cFile, id_open, 1+n, args, 0, 0, RB_PASS_CALLED_KEYWORDS);
}
else {
return rb_funcallv_kw(rb_cFile, id_open, 1+n, args, RB_PASS_CALLED_KEYWORDS);
}
} Открывает файл для чтения или записи.
См. File.open.
static VALUE
path_opendir(VALUE self)
{
VALUE args[1];
args[0] = get_strpath(self);
return rb_block_call(rb_cDir, id_open, 1, args, 0, 0);
} Открывает указанный каталог.
См. Dir.open.
static VALUE
path_owned_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_owned_p, 1, get_strpath(self));
} См. FileTest.owned?.
# File ext/pathname/lib/pathname.rb, line 194 def parent self + '..' end
Возвращает родительский каталог.
Это то же самое, что и self + '..'.
static VALUE
path_pipe_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_pipe_p, 1, get_strpath(self));
} См. FileTest.pipe?.
static VALUE
path_read(int argc, VALUE *argv, VALUE self)
{
VALUE args[4];
int n;
args[0] = get_strpath(self);
n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
return rb_funcallv_kw(rb_cFile, id_read, 1+n, args, RB_PASS_CALLED_KEYWORDS);
} Возвращает все данные из файла или первые N байт, если указано.
См. File.read.
static VALUE
path_readable_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_readable_p, 1, get_strpath(self));
} См. FileTest.readable?.
static VALUE
path_readable_real_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_readable_real_p, 1, get_strpath(self));
} static VALUE
path_readlines(int argc, VALUE *argv, VALUE self)
{
VALUE args[4];
int n;
args[0] = get_strpath(self);
n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
return rb_funcallv_kw(rb_cFile, id_readlines, 1+n, args, RB_PASS_CALLED_KEYWORDS);
} Возвращает все строки из файла.
См. File.readlines.
static VALUE
path_readlink(VALUE self)
{
VALUE str;
str = rb_funcall(rb_cFile, id_readlink, 1, get_strpath(self));
return rb_class_new_instance(1, &str, rb_obj_class(self));
} Чтение символической ссылки.
См. File.readlink.
static VALUE
path_realdirpath(int argc, VALUE *argv, VALUE self)
{
VALUE basedir, str;
rb_scan_args(argc, argv, "01", &basedir);
str = rb_funcall(rb_cFile, id_realdirpath, 2, get_strpath(self), basedir);
return rb_class_new_instance(1, &str, rb_obj_class(self));
} Возвращает реальное (абсолютное) имя пути self в фактической файловой системе.
Не содержит символических ссылок или бесполезных точек, .. и ..
Последний компонент реального пути может отсутствовать.
static VALUE
path_realpath(int argc, VALUE *argv, VALUE self)
{
VALUE basedir, str;
rb_scan_args(argc, argv, "01", &basedir);
str = rb_funcall(rb_cFile, id_realpath, 2, get_strpath(self), basedir);
return rb_class_new_instance(1, &str, rb_obj_class(self));
} Возвращает реальное (абсолютное) имя пути для self в фактической файловой системе.
Не содержит символических ссылок или бесполезных точек, .. и ..
Все компоненты пути должны существовать при вызове этого метода.
# File ext/pathname/lib/pathname.rb, line 246 def relative? !absolute? end
Противоположность Pathname#absolute?
Возвращает false, если имя пути начинается со слеша.
p = Pathname.new('/im/sure')
p.relative?
#=> false
p = Pathname.new('not/so/sure')
p.relative?
#=> true
# File ext/pathname/lib/pathname.rb, line 511
def relative_path_from(base_directory)
base_directory = Pathname.new(base_directory) unless base_directory.is_a? Pathname
dest_directory = self.cleanpath.to_s
base_directory = base_directory.cleanpath.to_s
dest_prefix = dest_directory
dest_names = []
while r = chop_basename(dest_prefix)
dest_prefix, basename = r
dest_names.unshift basename if basename != '.'
end
base_prefix = base_directory
base_names = []
while r = chop_basename(base_prefix)
base_prefix, basename = r
base_names.unshift basename if basename != '.'
end
unless SAME_PATHS[dest_prefix, base_prefix]
raise ArgumentError, "different prefix: #{dest_prefix.inspect} and #{base_directory.inspect}"
end
while !dest_names.empty? &&
!base_names.empty? &&
SAME_PATHS[dest_names.first, base_names.first]
dest_names.shift
base_names.shift
end
if base_names.include? '..'
raise ArgumentError, "base_directory has ..: #{base_directory.inspect}"
end
base_names.fill('..')
relpath_names = base_names + dest_names
if relpath_names.empty?
Pathname.new('.')
else
Pathname.new(File.join(*relpath_names))
end
end Возвращает относительный путь от заданного base_directory к получателю.
Если self является абсолютным, то base_directory также должен быть абсолютным.
Если self является относительным, то base_directory также должен быть относительным.
Этот метод не обращается к файловой системе. Он предполагает отсутствие символических ссылок.
ArgumentError вызывается, когда не удается найти относительный путь.
Обратите внимание, что этот метод не обрабатывает ситуации, когда регистрозависимость используемой файловой системы отличается от значения по умолчанию операционной системы.
static VALUE
path_rename(VALUE self, VALUE to)
{
return rb_funcall(rb_cFile, id_rename, 2, get_strpath(self), to);
} Переименовать файл.
См. File.rename.
static VALUE
path_rmdir(VALUE self)
{
return rb_funcall(rb_cDir, id_rmdir, 1, get_strpath(self));
} Удалить указанный каталог.
См. Dir.rmdir.
# File ext/pathname/lib/pathname.rb, line 592 def rmtree # The name "rmtree" is borrowed from File::Path of Perl. # File::Path provides "mkpath" and "rmtree". FileUtils.rm_r(@path) nil end
Рекурсивно удаляет каталог, включая все подкаталоги.
См. FileUtils.rm_r
# File ext/pathname/lib/pathname.rb, line 216
def root?
chop_basename(@path) == nil && /#{SEPARATOR_PAT}/o.match?(@path)
end Предикатный метод для корневых каталогов. Возвращает true, если имя пути состоит из последовательных слешей.
Он не обращается к файловой системе. Поэтому он может вернуть false для некоторых имен путей, указывающих на корни, такие как /usr/...
static VALUE
path_setgid_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_setgid_p, 1, get_strpath(self));
} См. FileTest.setgid?.
static VALUE
path_setuid_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_setuid_p, 1, get_strpath(self));
} См. FileTest.setuid?.
static VALUE
path_size(VALUE self)
{
return rb_funcall(rb_mFileTest, id_size, 1, get_strpath(self));
} См. FileTest.size.
static VALUE
path_size_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_size_p, 1, get_strpath(self));
} См. FileTest.size?.
static VALUE
path_socket_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_socket_p, 1, get_strpath(self));
} См. FileTest.socket?.
static VALUE
path_split(VALUE self)
{
VALUE str = get_strpath(self);
VALUE ary, dirname, basename;
ary = rb_funcall(rb_cFile, id_split, 1, str);
Check_Type(ary, T_ARRAY);
dirname = rb_ary_entry(ary, 0);
basename = rb_ary_entry(ary, 1);
dirname = rb_class_new_instance(1, &dirname, rb_obj_class(self));
basename = rb_class_new_instance(1, &basename, rb_obj_class(self));
return rb_ary_new3(2, dirname, basename);
} Возвращает dirname и basename в Array.
См. File.split.
static VALUE
path_stat(VALUE self)
{
return rb_funcall(rb_cFile, id_stat, 1, get_strpath(self));
} Возвращает объект File::Stat.
См. File.stat.
static VALUE
path_sticky_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_sticky_p, 1, get_strpath(self));
} См. FileTest.sticky?.
static VALUE
path_sub(int argc, VALUE *argv, VALUE self)
{
VALUE str = get_strpath(self);
if (rb_block_given_p()) {
str = rb_block_call(str, id_sub, argc, argv, 0, 0);
}
else {
str = rb_funcallv(str, id_sub, argc, argv);
}
return rb_class_new_instance(1, &str, rb_obj_class(self));
} Возвращает имя пути, которое заменяется String#sub.
path1 = Pathname.new('/usr/bin/perl')
path1.sub('perl', 'ruby')
#=> #<Pathname:/usr/bin/ruby>
static VALUE
path_sub_ext(VALUE self, VALUE repl)
{
VALUE str = get_strpath(self);
VALUE str2;
long extlen;
const char *ext;
const char *p;
StringValue(repl);
p = RSTRING_PTR(str);
extlen = RSTRING_LEN(str);
ext = ruby_enc_find_extname(p, &extlen, rb_enc_get(str));
if (ext == NULL) {
ext = p + RSTRING_LEN(str);
}
else if (extlen <= 1) {
ext += extlen;
}
str2 = rb_str_subseq(str, 0, ext-p);
rb_str_append(str2, repl);
return rb_class_new_instance(1, &str2, rb_obj_class(self));
} Возвращает имя пути с repl добавленным в качестве суффикса к базовому имени.
Если self не имеет части расширения, repl добавляется.
Pathname.new('/usr/bin/shutdown').sub_ext('.rb')
#=> #<Pathname:/usr/bin/shutdown.rb>
static VALUE
path_symlink_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_symlink_p, 1, get_strpath(self));
} См. FileTest.symlink?.
static VALUE
path_sysopen(int argc, VALUE *argv, VALUE self)
{
VALUE args[3];
int n;
args[0] = get_strpath(self);
n = rb_scan_args(argc, argv, "02", &args[1], &args[2]);
return rb_funcallv(rb_cIO, id_sysopen, 1+n, args);
} См. IO.sysopen.
static VALUE
path_taint(VALUE self)
{
rb_warn("Pathname#taint is deprecated and will be removed in Ruby 3.2.");
return self;
} Возвращает имя пути. Этот метод устарел и будет удален в Ruby 3.2.
static VALUE
path_to_s(VALUE self)
{
return rb_obj_dup(get_strpath(self));
} Возвращает путь в виде String.
to_path реализован таким образом, чтобы объекты Pathname можно было использовать с File.open и т.п.
static VALUE
path_truncate(VALUE self, VALUE length)
{
return rb_funcall(rb_cFile, id_truncate, 2, get_strpath(self), length);
} Усекает файл до length байтов.
См. File.truncate.
static VALUE
path_unlink(VALUE self)
{
VALUE eENOTDIR = rb_const_get_at(rb_mErrno, id_ENOTDIR);
VALUE str = get_strpath(self);
return rb_rescue2(unlink_body, str, unlink_rescue, str, eENOTDIR, (VALUE)0);
} Удаляет файл или директорию, используя File.unlink, если self — файл, или Dir.unlink при необходимости.
static VALUE
path_untaint(VALUE self)
{
rb_warn("Pathname#untaint is deprecated and will be removed in Ruby 3.2.");
return self;
} Возвращает путь. Этот метод устарел и будет удалён в Ruby 3.2.
static VALUE
path_utime(VALUE self, VALUE atime, VALUE mtime)
{
return rb_funcall(rb_cFile, id_utime, 3, atime, mtime, get_strpath(self));
} Обновляет время доступа и изменения файла.
См. File.utime.
static VALUE
path_world_readable_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_world_readable_p, 1, get_strpath(self));
} static VALUE
path_world_writable_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_world_writable_p, 1, get_strpath(self));
} static VALUE
path_writable_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_writable_p, 1, get_strpath(self));
} См. FileTest.writable?.
static VALUE
path_writable_real_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_writable_real_p, 1, get_strpath(self));
} static VALUE
path_write(int argc, VALUE *argv, VALUE self)
{
VALUE args[4];
int n;
args[0] = get_strpath(self);
n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
return rb_funcallv_kw(rb_cFile, id_write, 1+n, args, RB_PASS_CALLED_KEYWORDS);
} Записывает contents в файл.
См. File.write.
static VALUE
path_zero_p(VALUE self)
{
return rb_funcall(rb_mFileTest, id_zero_p, 1, get_strpath(self));
} См. FileTest.zero?.
Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.