модуль FileUtils
Пространство имён для методов работы с файлами: копирования, перемещения, удаления и т. д.
Что здесь
Сначала — о том, что находится в других местах. Модуль FileUtils:
-
Наследует от класса Object.
-
Дополняет класс File (но не включается в него и не расширяет его).
Модуль FileUtils предоставляет методы, полезные для:
Создание
-
::mkdir: создаёт каталоги. -
::mkdir_p,::makedirs,::mkpath: создают каталоги, а также при необходимости каталоги-предки. -
::link_entry: создаёт жёсткую ссылку. -
::ln_sf: создаёт символические ссылки, при необходимости перезаписывая существующие. -
::ln_sr: создаёт символические ссылки относительно целевых объектов
Удаление
-
::remove_dir: удаляет каталог и его содержимое. -
::remove_entry: удаляет запись, включая её содержимое, если это каталог. -
::remove_entry_secure: как::remove_entry, но выполняет безопасное удаление. -
::remove_file: удаляет файловую запись. -
::rm_f,::safe_unlink: как::rm, но выполняют принудительное удаление. -
::rm_r: удаляет записи и их содержимое. -
::rm_rf,::rmtree: как::rm_r, но выполняют принудительное удаление. -
::rmdir: удаляет каталоги.
Запросы
-
::uptodate?: возвращает сведения о том, новее ли заданная запись других заданных записей.
Настройка
-
::chmod: задаёт права доступа для записи. -
::chmod_R: задаёт права доступа для записи и её содержимого. -
::chown: задаёт владельца и группу для записей. -
::chown_R: задаёт владельца и группу для записей и их содержимого. -
::touch: задаёт время изменения и доступа для записей, при необходимости создавая их.
Сравнение
-
::compare_file,::cmp,::identical?: возвращают сведения о том, идентичны ли две записи. -
::compare_stream: возвращает сведения о том, идентичны ли два потока.
Копирование
-
::copy_entry: рекурсивно копирует запись. -
::copy_file: копирует запись. -
::copy_stream: копирует поток. -
::cp_lr: рекурсивно создаёт жёсткие ссылки. -
::cp_r: рекурсивно копирует файлы, сохраняя режим доступа, владельца и группу. -
::install: рекурсивно копирует файлы, при необходимости задавая режим доступа, владельца и группу.
Перемещение
Параметры
-
::collect_method: возвращает имена методов, принимающих заданный параметр. -
::commands: возвращает имена методов, принимающих параметры. -
::have_option?: возвращает сведения о том, принимает ли заданный метод заданный параметр. -
::options: возвращает все имена параметров. -
::options_of: возвращает имена параметров заданного метода.
Аргументы-пути
Некоторые методы FileUtils принимают аргументы path, которые интерпретируются как пути к записям файловой системы:
-
Если аргумент является строкой, её значение используется как путь.
-
Если у аргумента есть метод
:to_path, преобразование выполняется с помощью этого метода. -
Если у аргумента есть метод
:to_str, преобразование выполняется с помощью этого метода.
О примерах
Некоторые приведённые здесь примеры посвящены деревьям файловых записей. В таких случаях мы иногда отображаем деревья с помощью утилиты командной строки tree — рекурсивной утилиты для вывода содержимого каталогов, которая создаёт список файлов и каталогов с отступами, соответствующими глубине вложенности.
Для запуска команды и управления форматом вывода используется вспомогательный метод:
def tree(dirpath = '.')
command = "tree --noreport --charset=ascii #{dirpath}"
system(command)
end
Например:
tree('src0')
# => src0
# |-- sub0
# | |-- src0.txt
# | `-- src1.txt
# `-- sub1
# |-- src2.txt
# `-- src3.txt
Защита от уязвимости TOCTTOU
При рекурсивном удалении записей некоторыми методами существует потенциальная уязвимость, называемая уязвимостью «между проверкой и использованием» (Time-of-check to time-of-use, или TOCTTOU), которая может возникнуть, если:
-
Один из каталогов-предков записи по целевому пути доступен для записи всем пользователям; к таким каталогам относится
/tmp. -
Дерево каталогов по целевому пути содержит:
-
Вложенный каталог, доступный для записи всем пользователям.
-
Символическую ссылку.
-
Чтобы избежать этой уязвимости, для удаления записей можно использовать следующий метод:
-
FileUtils.remove_entry_secure: выполняет рекурсивное удаление, если целевой путь указывает на каталог.
Также доступны следующие методы, каждый из которых вызывает FileUtils.remove_entry_secure:
-
FileUtils.rm_rс именованным аргументомsecure: true. -
FileUtils.rm_rfс именованным аргументомsecure: true.
Наконец, этот метод перемещения записей вызывает FileUtils.remove_entry_secure, если источник и место назначения находятся в разных файловых системах (то есть «перемещение» фактически выполняется копированием и удалением):
-
FileUtils.mvс именованным аргументомsecure: true.
Метод FileUtils.remove_entry_secure выполняет безопасное удаление, применяя специальную предварительную обработку:
-
Если целевой путь указывает на каталог, при удалении каталогов этот метод использует методы
File#chownиFile#chmod. -
Владельцем целевого каталога должен быть текущий процесс или суперпользователь (root).
ПРЕДУПРЕЖДЕНИЕ: необходимо убедиться, что ВСЕ родительские каталоги защищены от перемещения другими недоверенными пользователями. Например, владельцами родительских каталогов не должны быть недоверенные пользователи, а сами каталоги не должны быть доступны для записи всем пользователям, кроме случаев, когда установлен бит sticky.
Подробности об этой уязвимости безопасности см. в следующих случаях Perl:
Константы
- VERSION
-
Номер версии.
Открытые методы класса
# File lib/fileutils.rb, line 239
def cd(dir, verbose: nil, &block) # :yield: dir
fu_output_message "cd #{dir}" if verbose
result = Dir.chdir(dir, &block)
fu_output_message 'cd -' if verbose and block
result
end Изменяет рабочий каталог на заданный dir, который должен быть интерпретируем как путь:
Если блок не передан, изменяет текущий каталог на каталог по адресу dir; возвращает ноль:
FileUtils.pwd # => "/rdoc/fileutils"
FileUtils.cd('..')
FileUtils.pwd # => "/rdoc"
FileUtils.cd('fileutils')
Если блок передан, изменяет текущий каталог на каталог по адресу dir, вызывает блок с аргументом dir и восстанавливает исходный текущий каталог; возвращает значение блока:
FileUtils.pwd # => "/rdoc/fileutils"
FileUtils.cd('..') { |arg| [arg, FileUtils.pwd] } # => ["..", "/rdoc"]
FileUtils.pwd # => "/rdoc/fileutils"
Именованные аргументы:
-
verbose: true— выводит эквивалентную команду:FileUtils.cd('..') FileUtils.cd('fileutils')Вывод:
cd .. cd fileutils
Связанный метод: FileUtils.pwd.
# File lib/fileutils.rb, line 1804
def chmod(mode, list, noop: nil, verbose: nil)
list = fu_list(list)
fu_output_message sprintf('chmod %s %s', mode_to_s(mode), list.join(' ')) if verbose
return if noop
list.each do |path|
Entry_.new(path).chmod(fu_mode(mode, path))
end
end Изменяет разрешения для записей по путям, заданным в list (один путь или массив путей), на разрешения, заданные в mode; возвращает list, если это массив, и [list] в противном случае:
-
Изменяет каждую запись, являющуюся обычным файлом, с помощью
File.chmod. -
Изменяет каждую запись, являющуюся символической ссылкой, с помощью
File.lchmod.
Аргумент list или его элементы должны быть интерпретируемы как пути.
Аргумент mode может быть целым числом или строкой:
-
Целое число
mode: задаёт устанавливаемые биты разрешений:FileUtils.chmod(0755, 'src0.txt') FileUtils.chmod(0644, ['src0.txt', 'src0.dat'])
-
Строка
mode: задаёт устанавливаемые разрешения:Строка имеет формат
[targets][[operator][perms[,perms]], где:-
targetsможет состоять из любой комбинации следующих букв:-
'u': разрешения применяются к владельцу файла. -
'g': разрешения применяются к пользователям из группы файла. -
'o': разрешения применяются к пользователям, не входящим в группу файла. -
'a'(по умолчанию): разрешения применяются ко всем пользователям.
-
-
operatorможет быть одной из следующих букв:-
'+': добавляет разрешения. -
'-': удаляет разрешения. -
'=': устанавливает (заменяет) разрешения.
-
-
perms(может повторяться; элементы разделяются запятыми) может состоять из любой комбинации следующих букв:-
'r': чтение. -
'w': запись. -
'x': выполнение (поиск для каталога). -
'X': поиск (только для каталогов; должен использоваться с'+') -
's': uid или gid. -
't': бит закрепления.
-
Примеры:
FileUtils.chmod('u=wrx,go=rx', 'src1.txt') FileUtils.chmod('u=wrx,go=rx', '/usr/bin/ruby') -
Именованные аргументы:
-
noop: true— не изменяет разрешения; возвращаетnil. -
verbose: true— выводит эквивалентную команду:FileUtils.chmod(0755, 'src0.txt', noop: true, verbose: true) FileUtils.chmod(0644, ['src0.txt', 'src0.dat'], noop: true, verbose: true) FileUtils.chmod('u=wrx,go=rx', 'src1.txt', noop: true, verbose: true) FileUtils.chmod('u=wrx,go=rx', '/usr/bin/ruby', noop: true, verbose: true)Вывод:
chmod 755 src0.txt chmod 644 src0.txt src0.dat chmod u=wrx,go=rx src1.txt chmod u=wrx,go=rx /usr/bin/ruby
Связанный метод: FileUtils.chmod_R.
# File lib/fileutils.rb, line 1816
def chmod_R(mode, list, noop: nil, verbose: nil, force: nil)
list = fu_list(list)
fu_output_message sprintf('chmod -R%s %s %s',
(force ? 'f' : ''),
mode_to_s(mode), list.join(' ')) if verbose
return if noop
list.each do |root|
Entry_.new(root).traverse do |ent|
begin
ent.chmod(fu_mode(mode, ent.path))
rescue
raise unless force
end
end
end
end Подобно FileUtils.chmod, но рекурсивно изменяет разрешения.
# File lib/fileutils.rb, line 1897
def chown(user, group, list, noop: nil, verbose: nil)
list = fu_list(list)
fu_output_message sprintf('chown %s %s',
(group ? "#{user}:#{group}" : user || ':'),
list.join(' ')) if verbose
return if noop
uid = fu_get_uid(user)
gid = fu_get_gid(group)
list.each do |path|
Entry_.new(path).chown uid, gid
end
end Изменяет владельца и группу для записей по путям, заданным в list (один путь или массив путей), на указанные user и group; возвращает list, если это массив, и [list] в противном случае:
-
Изменяет каждую запись, являющуюся обычным файлом, с помощью
File.chown. -
Изменяет каждую запись, являющуюся символической ссылкой, с помощью
File.lchown.
Аргумент list или его элементы должны быть интерпретируемы как пути.
Пользователь и группа:
-
Аргумент
userможет быть именем пользователя или идентификатором пользователя; если он равенnilили-1, пользователь не изменяется. -
Аргумент
groupможет быть именем группы или идентификатором группы; если он равенnilили-1, группа не изменяется. -
Пользователь должен входить в группу.
Примеры:
# One path.
# User and group as string names.
File.stat('src0.txt').uid # => 1004
File.stat('src0.txt').gid # => 1004
FileUtils.chown('user2', 'group1', 'src0.txt')
File.stat('src0.txt').uid # => 1006
File.stat('src0.txt').gid # => 1005
# User and group as uid and gid.
FileUtils.chown(1004, 1004, 'src0.txt')
File.stat('src0.txt').uid # => 1004
File.stat('src0.txt').gid # => 1004
# Array of paths.
FileUtils.chown(1006, 1005, ['src0.txt', 'src0.dat'])
# Directory (not recursive).
FileUtils.chown('user2', 'group1', '.')
Именованные аргументы:
-
noop: true— не изменяет разрешения; возвращаетnil. -
verbose: true— выводит эквивалентную команду:FileUtils.chown('user2', 'group1', 'src0.txt', noop: true, verbose: true) FileUtils.chown(1004, 1004, 'src0.txt', noop: true, verbose: true) FileUtils.chown(1006, 1005, ['src0.txt', 'src0.dat'], noop: true, verbose: true) FileUtils.chown('user2', 'group1', path, noop: true, verbose: true) FileUtils.chown('user2', 'group1', '.', noop: true, verbose: true)Вывод:
chown user2:group1 src0.txt chown 1004:1004 src0.txt chown 1006:1005 src0.txt src0.dat chown user2:group1 src0.txt chown user2:group1 .
Связанный метод: FileUtils.chown_R.
# File lib/fileutils.rb, line 1913
def chown_R(user, group, list, noop: nil, verbose: nil, force: nil)
list = fu_list(list)
fu_output_message sprintf('chown -R%s %s %s',
(force ? 'f' : ''),
(group ? "#{user}:#{group}" : user || ':'),
list.join(' ')) if verbose
return if noop
uid = fu_get_uid(user)
gid = fu_get_gid(group)
list.each do |root|
Entry_.new(root).traverse do |ent|
begin
ent.chown uid, gid
rescue
raise unless force
end
end
end
end Подобно FileUtils.chown, но рекурсивно изменяет владельца и группу.
# File lib/fileutils.rb, line 2611
def self.collect_method(opt)
OPT_TABLE.keys.select {|m| OPT_TABLE[m].include?(opt) }
end Возвращает массив строковых имен методов, принимающих заданный именованный параметр opt; аргумент должен быть символом:
FileUtils.collect_method(:preserve) # => ["cp", "copy", "cp_r", "install"]
# File lib/fileutils.rb, line 2572 def self.commands OPT_TABLE.keys end
Возвращает массив строковых имен методов FileUtils, принимающих один или несколько именованных аргументов:
FileUtils.commands.sort.take(3) # => ["cd", "chdir", "chmod"]
# File lib/fileutils.rb, line 1508
def compare_file(a, b)
return false unless File.size(a) == File.size(b)
File.open(a, 'rb') {|fa|
File.open(b, 'rb') {|fb|
return compare_stream(fa, fb)
}
}
end Возвращает true, если содержимое файлов a и b идентично, и false в противном случае.
Аргументы a и b должны быть интерпретируемы как путь.
FileUtils.identical? и FileUtils.cmp являются псевдонимами для FileUtils.compare_file.
Связанный метод: FileUtils.compare_stream.
# File lib/fileutils.rb, line 1531
def compare_stream(a, b)
bsize = fu_stream_blksize(a, b)
sa = String.new(capacity: bsize)
sb = String.new(capacity: bsize)
begin
a.read(bsize, sa)
b.read(bsize, sb)
return true if sa.empty? && sb.empty?
end while sa == sb
false
end Возвращает true, если содержимое потоков a и b идентично, и false в противном случае.
Аргументы a и b должны быть интерпретируемы как путь.
Связанный метод: FileUtils.compare_file.
# File lib/fileutils.rb, line 1041
def copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false)
if dereference_root
src = File.realpath(src)
end
Entry_.new(src, nil, false).wrap_traverse(proc do |ent|
destent = Entry_.new(dest, ent.rel, false)
File.unlink destent.path if remove_destination && (File.file?(destent.path) || File.symlink?(destent.path))
ent.copy destent.path
end, proc do |ent|
destent = Entry_.new(dest, ent.rel, false)
ent.copy_metadata destent.path if preserve
end)
end Рекурсивно копирует файлы из src в dest.
Аргументы src и dest должны быть интерпретируемы как пути.
Если src — путь к файлу, копирует src в dest:
FileUtils.touch('src0.txt')
File.exist?('dest0.txt') # => false
FileUtils.copy_entry('src0.txt', 'dest0.txt')
File.file?('dest0.txt') # => true
Если src — каталог, рекурсивно копирует src в dest:
tree('src1')
# => src1
# |-- dir0
# | |-- src0.txt
# | `-- src1.txt
# `-- dir1
# |-- src2.txt
# `-- src3.txt
FileUtils.copy_entry('src1', 'dest1')
tree('dest1')
# => dest1
# |-- dir0
# | |-- src0.txt
# | `-- src1.txt
# `-- dir1
# |-- src2.txt
# `-- src3.txt
При рекурсивном копировании сохраняются типы обычных файлов, каталогов и символических ссылок; другие типы файлов (потоки FIFO, файлы устройств и т. д.) не поддерживаются.
Именованные аргументы:
-
dereference_root: true— еслиsrcявляется символической ссылкой, следует по ссылке. -
preserve: true— сохраняет время изменения файлов. -
remove_destination: true— удаляетdestперед копированием файлов.
Связанные методы: методы копирования.
# File lib/fileutils.rb, line 1077 def copy_file(src, dest, preserve = false, dereference = true) ent = Entry_.new(src, nil, dereference) ent.copy_file dest ent.copy_metadata dest if preserve end
Копирует файл из src в dest; эти пути не должны указывать на каталоги.
Аргументы src и dest должны быть интерпретируемы как пути.
Примеры:
FileUtils.touch('src0.txt')
FileUtils.copy_file('src0.txt', 'dest0.txt')
File.file?('dest0.txt') # => true
Именованные аргументы:
-
dereference: false— еслиsrcявляется символической ссылкой, не следует по ссылке. -
preserve: true— сохраняет время изменения файлов. -
remove_destination: true— удаляетdestперед копированием файлов.
Связанные методы: методы копирования.
# File lib/fileutils.rb, line 1089 def copy_stream(src, dest) IO.copy_stream(src, dest) end
Копирует поток ввода-вывода src в поток ввода-вывода dest с помощью IO.copy_stream.
Связанные методы: методы копирования.
# File lib/fileutils.rb, line 874
def cp(src, dest, preserve: nil, noop: nil, verbose: nil)
fu_output_message "cp#{preserve ? ' -p' : ''} #{[src,dest].flatten.join ' '}" if verbose
return if noop
fu_each_src_dest(src, dest) do |s, d|
copy_file s, d, preserve
end
end Копирует файлы.
Аргументы src (один путь или массив путей) и dest (один путь) должны быть интерпретируемы как пути.
Если src — путь к файлу, а dest не является путем к каталогу, копирует src в dest:
FileUtils.touch('src0.txt')
File.exist?('dest0.txt') # => false
FileUtils.cp('src0.txt', 'dest0.txt')
File.file?('dest0.txt') # => true
Если src — путь к файлу, а dest — путь к каталогу, копирует src в dest/src:
FileUtils.touch('src1.txt')
FileUtils.mkdir('dest1')
FileUtils.cp('src1.txt', 'dest1')
File.file?('dest1/src1.txt') # => true
Если src — массив путей к файлам, а dest — путь к каталогу, копирует каждый src в dest:
src_file_paths = ['src2.txt', 'src2.dat']
FileUtils.touch(src_file_paths)
FileUtils.mkdir('dest2')
FileUtils.cp(src_file_paths, 'dest2')
File.file?('dest2/src2.txt') # => true
File.file?('dest2/src2.dat') # => true
Именованные аргументы:
-
preserve: true— сохраняет время изменения файлов. -
noop: true— не копирует файлы. -
verbose: true— выводит эквивалентную команду:FileUtils.cp('src0.txt', 'dest0.txt', noop: true, verbose: true) FileUtils.cp('src1.txt', 'dest1', noop: true, verbose: true) FileUtils.cp(src_file_paths, 'dest2', noop: true, verbose: true)Вывод:
cp src0.txt dest0.txt cp src1.txt dest1 cp src2.txt src2.dat dest2
Вызывает исключение, если src является каталогом.
Связанные методы: методы копирования.
# File lib/fileutils.rb, line 628
def cp_lr(src, dest, noop: nil, verbose: nil,
dereference_root: true, remove_destination: false)
fu_output_message "cp -lr#{remove_destination ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if verbose
return if noop
fu_each_src_dest(src, dest) do |s, d|
link_entry s, d, dereference_root, remove_destination
end
end Создает жесткие ссылки.
Аргументы src (один путь или массив путей) и dest (один путь) должны быть интерпретируемы как пути.
Если src — путь к каталогу, а dest не существует, создает ссылки dest и вложенных элементов, указывающие на src и его вложенные элементы:
tree('src0')
# => src0
# |-- sub0
# | |-- src0.txt
# | `-- src1.txt
# `-- sub1
# |-- src2.txt
# `-- src3.txt
File.exist?('dest0') # => false
FileUtils.cp_lr('src0', 'dest0')
tree('dest0')
# => dest0
# |-- sub0
# | |-- src0.txt
# | `-- src1.txt
# `-- sub1
# |-- src2.txt
# `-- src3.txt
Если src и dest — пути к каталогам, создает ссылки dest/src и вложенных элементов, указывающие на src и его вложенные элементы:
tree('src1')
# => src1
# |-- sub0
# | |-- src0.txt
# | `-- src1.txt
# `-- sub1
# |-- src2.txt
# `-- src3.txt
FileUtils.mkdir('dest1')
FileUtils.cp_lr('src1', 'dest1')
tree('dest1')
# => dest1
# `-- src1
# |-- sub0
# | |-- src0.txt
# | `-- src1.txt
# `-- sub1
# |-- src2.txt
# `-- src3.txt
Если src — массив путей к записям, а dest — путь к каталогу, для каждого пути filepath в src создает ссылку по адресу dest/filepath, указывающую на этот путь:
tree('src2')
# => src2
# |-- sub0
# | |-- src0.txt
# | `-- src1.txt
# `-- sub1
# |-- src2.txt
# `-- src3.txt
FileUtils.mkdir('dest2')
FileUtils.cp_lr(['src2/sub0', 'src2/sub1'], 'dest2')
tree('dest2')
# => dest2
# |-- sub0
# | |-- src0.txt
# | `-- src1.txt
# `-- sub1
# |-- src2.txt
# `-- src3.txt
Именованные аргументы:
-
dereference_root: false— еслиsrcявляется символической ссылкой, не разыменовывает ее. -
noop: true— не создает ссылки. -
remove_destination: true— удаляетdestперед созданием ссылок. -
verbose: true— выводит эквивалентную команду:FileUtils.cp_lr('src0', 'dest0', noop: true, verbose: true) FileUtils.cp_lr('src1', 'dest1', noop: true, verbose: true) FileUtils.cp_lr(['src2/sub0', 'src2/sub1'], 'dest2', noop: true, verbose: true)Вывод:
cp -lr src0 dest0 cp -lr src1 dest1 cp -lr src2/sub0 src2/sub1 dest2
Вызывает исключение, если dest — путь к существующему файлу или каталогу и не задан именованный аргумент remove_destination: true.
Связанные методы: методы копирования.
# File lib/fileutils.rb, line 986
def cp_r(src, dest, preserve: nil, noop: nil, verbose: nil,
dereference_root: true, remove_destination: nil)
fu_output_message "cp -r#{preserve ? 'p' : ''}#{remove_destination ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if verbose
return if noop
fu_each_src_dest(src, dest) do |s, d|
copy_entry s, d, preserve, dereference_root, remove_destination
end
end Рекурсивно копирует файлы.
Аргументы src (один путь или массив путей) и dest (один путь) должны быть интерпретируемы как пути.
Режим доступа, владелец и группа сохраняются при копировании; чтобы изменить их, используйте вместо этого FileUtils.install.
Если src — путь к файлу, а dest не является путем к каталогу, копирует src в dest:
FileUtils.touch('src0.txt')
File.exist?('dest0.txt') # => false
FileUtils.cp_r('src0.txt', 'dest0.txt')
File.file?('dest0.txt') # => true
Если src — путь к файлу, а dest — путь к каталогу, копирует src в dest/src:
FileUtils.touch('src1.txt')
FileUtils.mkdir('dest1')
FileUtils.cp_r('src1.txt', 'dest1')
File.file?('dest1/src1.txt') # => true
Если src — путь к каталогу, а dest не существует, рекурсивно копирует src в dest:
tree('src2')
# => src2
# |-- dir0
# | |-- src0.txt
# | `-- src1.txt
# `-- dir1
# |-- src2.txt
# `-- src3.txt
FileUtils.exist?('dest2') # => false
FileUtils.cp_r('src2', 'dest2')
tree('dest2')
# => dest2
# |-- dir0
# | |-- src0.txt
# | `-- src1.txt
# `-- dir1
# |-- src2.txt
# `-- src3.txt
Если src и dest — пути к каталогам, рекурсивно копирует src в dest/src:
tree('src3')
# => src3
# |-- dir0
# | |-- src0.txt
# | `-- src1.txt
# `-- dir1
# |-- src2.txt
# `-- src3.txt
FileUtils.mkdir('dest3')
FileUtils.cp_r('src3', 'dest3')
tree('dest3')
# => dest3
# `-- src3
# |-- dir0
# | |-- src0.txt
# | `-- src1.txt
# `-- dir1
# |-- src2.txt
# `-- src3.txt
Если src — массив путей, а dest — каталог, рекурсивно копирует содержимое каждого пути из src в dest; пути в src могут указывать на файлы и/или каталоги.
Именованные аргументы:
-
dereference_root: false— еслиsrcявляется символической ссылкой, не разыменовывает ее. -
noop: true— не копирует файлы. -
preserve: true— сохраняет время изменения файлов. -
remove_destination: true— удаляетdestперед копированием файлов. -
verbose: true— выводит эквивалентную команду:FileUtils.cp_r('src0.txt', 'dest0.txt', noop: true, verbose: true) FileUtils.cp_r('src1.txt', 'dest1', noop: true, verbose: true) FileUtils.cp_r('src2', 'dest2', noop: true, verbose: true) FileUtils.cp_r('src3', 'dest3', noop: true, verbose: true)Вывод:
cp -r src0.txt dest0.txt cp -r src1.txt dest1 cp -r src2 dest2 cp -r src3 dest3
Вызывает исключение, если src — путь к каталогу, а dest — путь к файлу.
Связанные методы: методы копирования.
# File lib/fileutils.rb, line 2590
def self.have_option?(mid, opt)
li = OPT_TABLE[mid.to_s] or raise ArgumentError, "no such method: #{mid}"
li.include?(opt)
end Возвращает true, если метод mid принимает заданный параметр opt, и false в противном случае; аргументы могут быть строками или символами:
FileUtils.have_option?(:chmod, :noop) # => true
FileUtils.have_option?('chmod', 'secure') # => false
# File lib/fileutils.rb, line 1610
def install(src, dest, mode: nil, owner: nil, group: nil, preserve: nil,
noop: nil, verbose: nil)
if verbose
msg = +"install -c"
msg << ' -p' if preserve
msg << ' -m ' << mode_to_s(mode) if mode
msg << " -o #{owner}" if owner
msg << " -g #{group}" if group
msg << ' ' << [src,dest].flatten.join(' ')
fu_output_message msg
end
return if noop
uid = fu_get_uid(owner)
gid = fu_get_gid(group)
fu_each_src_dest(src, dest) do |s, d|
st = File.stat(s)
unless File.exist?(d) and compare_file(s, d)
remove_file d, true
if d.end_with?('/')
mkdir_p d
copy_file s, d + File.basename(s)
else
mkdir_p File.expand_path('..', d)
copy_file s, d
end
File.utime st.atime, st.mtime, d if preserve
File.chmod fu_mode(mode, st), d if mode
File.chown uid, gid, d if uid or gid
end
end
end Копирует файловую запись. См. install(1).
Аргументы src (один путь или массив путей) и dest (один путь) должны быть интерпретируемы как пути;
Если запись по адресу dest не существует, копирует из src в dest:
File.read('src0.txt') # => "aaa\n"
File.exist?('dest0.txt') # => false
FileUtils.install('src0.txt', 'dest0.txt')
File.read('dest0.txt') # => "aaa\n"
Если dest — файловая запись, копирует из src в dest, перезаписывая ее:
File.read('src1.txt') # => "aaa\n"
File.read('dest1.txt') # => "bbb\n"
FileUtils.install('src1.txt', 'dest1.txt')
File.read('dest1.txt') # => "aaa\n"
Если dest — запись каталога, копирует из src в dest/src, при необходимости перезаписывая:
File.read('src2.txt') # => "aaa\n"
File.read('dest2/src2.txt') # => "bbb\n"
FileUtils.install('src2.txt', 'dest2')
File.read('dest2/src2.txt') # => "aaa\n"
Если src — массив путей, а dest указывает на каталог, копирует каждый путь path из src в dest/path:
File.file?('src3.txt') # => true
File.file?('src3.dat') # => true
FileUtils.mkdir('dest3')
FileUtils.install(['src3.txt', 'src3.dat'], 'dest3')
File.file?('dest3/src3.txt') # => true
File.file?('dest3/src3.dat') # => true
Именованные аргументы:
-
group: group— изменяет группу, если она не равнаnil, с помощьюFile.chown. -
mode: permissions— изменяет разрешения с помощьюFile.chmod. -
noop: true— не копирует записи; возвращаетnil. -
owner: owner— изменяет владельца, если он не равенnil, с помощьюFile.chown. -
preserve: true— сохраняет временные метки с помощьюFile.utime. -
verbose: true— выводит эквивалентную команду:FileUtils.install('src0.txt', 'dest0.txt', noop: true, verbose: true) FileUtils.install('src1.txt', 'dest1.txt', noop: true, verbose: true) FileUtils.install('src2.txt', 'dest2', noop: true, verbose: true)Вывод:
install -c src0.txt dest0.txt install -c src1.txt dest1.txt install -c src2.txt dest2
Связанные методы: методы копирования.
# File lib/fileutils.rb, line 813
def link_entry(src, dest, dereference_root = false, remove_destination = false)
Entry_.new(src, nil, dereference_root).traverse do |ent|
destent = Entry_.new(dest, ent.rel, false)
File.unlink destent.path if remove_destination && File.file?(destent.path)
ent.link destent.path
end
end Создает жесткие ссылки; возвращает nil.
Аргументы src и dest должны быть интерпретируемы как пути.
Если src — путь к файлу, а dest не существует, создает жесткую ссылку по адресу dest, указывающую на src:
FileUtils.touch('src0.txt')
File.exist?('dest0.txt') # => false
FileUtils.link_entry('src0.txt', 'dest0.txt')
File.file?('dest0.txt') # => true
Если src — путь к каталогу, а dest не существует, рекурсивно создает жесткие ссылки по адресам dest, указывающие на пути в src:
FileUtils.mkdir_p(['src1/dir0', 'src1/dir1'])
src_file_paths = [
'src1/dir0/t0.txt',
'src1/dir0/t1.txt',
'src1/dir1/t2.txt',
'src1/dir1/t3.txt',
]
FileUtils.touch(src_file_paths)
File.directory?('dest1') # => true
FileUtils.link_entry('src1', 'dest1')
File.file?('dest1/dir0/t0.txt') # => true
File.file?('dest1/dir0/t1.txt') # => true
File.file?('dest1/dir1/t2.txt') # => true
File.file?('dest1/dir1/t3.txt') # => true
Именованные аргументы:
-
dereference_root: true— разыменовываетsrc, если это символическая ссылка. -
remove_destination: true— удаляетdestперед созданием ссылок.
Вызывает исключение, если dest — путь к существующему файлу или каталогу и не задан именованный аргумент remove_destination: true.
Связанный метод: FileUtils.ln (имеет другие параметры).
# File lib/fileutils.rb, line 517
def ln(src, dest, force: nil, noop: nil, verbose: nil)
fu_output_message "ln#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose
return if noop
fu_each_src_dest0(src, dest) do |s,d|
remove_file d, true if force
File.link s, d
end
end Создаёт жёсткие ссылки.
Аргументы src (один путь или массив путей) и dest (один путь) должны интерпретироваться как пути.
Если src — путь к существующему файлу, а dest — путь к несуществующему файлу, создаёт жёсткую ссылку в dest, указывающую на src; возвращает ноль:
Dir.children('tmp0/') # => ["t.txt"]
Dir.children('tmp1/') # => []
FileUtils.ln('tmp0/t.txt', 'tmp1/t.lnk') # => 0
Dir.children('tmp1/') # => ["t.lnk"]
Если src — путь к существующему файлу, а dest — путь к существующему каталогу, создаёт жёсткую ссылку в dest/src, указывающую на src; возвращает ноль:
Dir.children('tmp2') # => ["t.dat"]
Dir.children('tmp3') # => []
FileUtils.ln('tmp2/t.dat', 'tmp3') # => 0
Dir.children('tmp3') # => ["t.dat"]
Если src — массив путей к существующим файлам, а dest — путь к существующему каталогу, то для каждого пути target в src создаёт жёсткую ссылку в dest/target, указывающую на target; возвращает src:
Dir.children('tmp4/') # => []
FileUtils.ln(['tmp0/t.txt', 'tmp2/t.dat'], 'tmp4/') # => ["tmp0/t.txt", "tmp2/t.dat"]
Dir.children('tmp4/') # => ["t.dat", "t.txt"]
Именованные аргументы:
-
force: true— перезаписываетdest, если он существует. -
noop: true— не создаёт ссылки. -
verbose: true— выводит эквивалентную команду:FileUtils.ln('tmp0/t.txt', 'tmp1/t.lnk', verbose: true) FileUtils.ln('tmp2/t.dat', 'tmp3', verbose: true) FileUtils.ln(['tmp0/t.txt', 'tmp2/t.dat'], 'tmp4/', verbose: true)Вывод:
ln tmp0/t.txt tmp1/t.lnk ln tmp2/t.dat tmp3 ln tmp0/t.txt tmp2/t.dat tmp4/
Вызывает исключение, если dest — путь к существующему файлу, а именованный аргумент force не равен true.
Связанный метод: FileUtils.link_entry (имеет другие параметры).
# File lib/fileutils.rb, line 707
def ln_s(src, dest, force: nil, relative: false, target_directory: true, noop: nil, verbose: nil)
if relative
return ln_sr(src, dest, force: force, noop: noop, verbose: verbose)
end
fu_output_message "ln -s#{force ? 'f' : ''} #{[src,dest].flatten.join ' '}" if verbose
return if noop
fu_each_src_dest0(src, dest) do |s,d|
remove_file d, true if force
File.symlink s, d
end
end Создаёт символические ссылки.
Аргументы src (один путь или массив путей) и dest (один путь) должны интерпретироваться как пути.
Если src — путь к существующему файлу:
-
Если
dest— путь к несуществующему файлу, создаёт символическую ссылку вdest, указывающую наsrc:FileUtils.touch('src0.txt') File.exist?('dest0.txt') # => false FileUtils.ln_s('src0.txt', 'dest0.txt') File.symlink?('dest0.txt') # => true -
Если
dest— путь к существующему файлу, создаёт символическую ссылку вdest, указывающую наsrc, только если указан именованный аргументforce: true(в противном случае вызывает исключение):FileUtils.touch('src1.txt') FileUtils.touch('dest1.txt') FileUtils.ln_s('src1.txt', 'dest1.txt', force: true) FileTest.symlink?('dest1.txt') # => true FileUtils.ln_s('src1.txt', 'dest1.txt') # Raises Errno::EEXIST.
Если dest — путь к каталогу, создаёт символическую ссылку в dest/src, указывающую на src:
FileUtils.touch('src2.txt')
FileUtils.mkdir('destdir2')
FileUtils.ln_s('src2.txt', 'destdir2')
File.symlink?('destdir2/src2.txt') # => true
Если src — массив путей к существующим файлам, а dest — каталог, для каждого дочернего элемента child в src создаёт символическую ссылку dest/child, указывающую на child:
FileUtils.mkdir('srcdir3')
FileUtils.touch('srcdir3/src0.txt')
FileUtils.touch('srcdir3/src1.txt')
FileUtils.mkdir('destdir3')
FileUtils.ln_s(['srcdir3/src0.txt', 'srcdir3/src1.txt'], 'destdir3')
File.symlink?('destdir3/src0.txt') # => true
File.symlink?('destdir3/src1.txt') # => true
Именованные аргументы:
-
force: true— перезаписываетdest, если он существует. -
relative: false— создаёт ссылки относительноdest. -
noop: true— не создаёт ссылки. -
verbose: true— выводит эквивалентную команду:FileUtils.ln_s('src0.txt', 'dest0.txt', noop: true, verbose: true) FileUtils.ln_s('src1.txt', 'destdir1', noop: true, verbose: true) FileUtils.ln_s('src2.txt', 'dest2.txt', force: true, noop: true, verbose: true) FileUtils.ln_s(['srcdir3/src0.txt', 'srcdir3/src1.txt'], 'destdir3', noop: true, verbose: true)Вывод:
ln -s src0.txt dest0.txt ln -s src1.txt destdir1 ln -sf src2.txt dest2.txt ln -s srcdir3/src0.txt srcdir3/src1.txt destdir3
Связанный метод: FileUtils.ln_sf.
# File lib/fileutils.rb, line 725 def ln_sf(src, dest, noop: nil, verbose: nil) ln_s src, dest, force: true, noop: noop, verbose: verbose end
Подобен FileUtils.ln_s, но именованный аргумент force: true указывается всегда.
# File lib/fileutils.rb, line 732
def ln_sr(src, dest, target_directory: true, force: nil, noop: nil, verbose: nil)
options = "#{force ? 'f' : ''}#{target_directory ? '' : 'T'}"
dest = File.path(dest)
srcs = Array(src)
link = proc do |s, target_dir_p = true|
s = File.path(s)
if target_dir_p
d = File.join(destdirs = dest, File.basename(s))
else
destdirs = File.dirname(d = dest)
end
destdirs = fu_split_path(File.realpath(destdirs))
if fu_starting_path?(s)
srcdirs = fu_split_path((File.realdirpath(s) rescue File.expand_path(s)))
base = fu_relative_components_from(srcdirs, destdirs)
s = File.join(*base)
else
srcdirs = fu_clean_components(*fu_split_path(s))
base = fu_relative_components_from(fu_split_path(Dir.pwd), destdirs)
while srcdirs.first&. == ".." and base.last&.!=("..") and !fu_starting_path?(base.last)
srcdirs.shift
base.pop
end
s = File.join(*base, *srcdirs)
end
fu_output_message "ln -s#{options} #{s} #{d}" if verbose
next if noop
remove_file d, true if force
File.symlink s, d
end
case srcs.size
when 0
when 1
link[srcs[0], target_directory && File.directory?(dest)]
else
srcs.each(&link)
end
end Подобен FileUtils.ln_s, но создаёт ссылки относительно dest.
# File lib/fileutils.rb, line 317
def mkdir(list, mode: nil, noop: nil, verbose: nil)
list = fu_list(list)
fu_output_message "mkdir #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}" if verbose
return if noop
list.each do |dir|
fu_mkdir dir, mode
end
end Создаёт каталоги по путям из заданного list (один путь или массив путей); если это массив, возвращает list, в противном случае — [list].
Аргумент list или его элементы должны интерпретироваться как пути.
Если именованные аргументы не заданы, создаёт каталог для каждого path в list, вызывая: Dir.mkdir(path, mode); см. Dir.mkdir:
FileUtils.mkdir(%w[tmp0 tmp1]) # => ["tmp0", "tmp1"]
FileUtils.mkdir('tmp4') # => ["tmp4"]
Именованные аргументы:
-
mode: mode— также вызываетFile.chmod(mode, path); см.File.chmod. -
noop: true— не создаёт каталоги. -
verbose: true— выводит эквивалентную команду:FileUtils.mkdir(%w[tmp0 tmp1], verbose: true) FileUtils.mkdir(%w[tmp2 tmp3], mode: 0700, verbose: true)
Вывод:
mkdir tmp0 tmp1 mkdir -m 700 tmp2 tmp3
Вызывает исключение, если какой-либо путь указывает на существующий файл или каталог либо если по какой-либо причине не удаётся создать каталог.
Связанный метод: FileUtils.mkdir_p.
# File lib/fileutils.rb, line 366
def mkdir_p(list, mode: nil, noop: nil, verbose: nil)
list = fu_list(list)
fu_output_message "mkdir -p #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}" if verbose
return *list if noop
list.each do |item|
path = remove_trailing_slash(item)
stack = []
until File.directory?(path) || File.dirname(path) == path
stack.push path
path = File.dirname(path)
end
stack.reverse_each do |dir|
begin
fu_mkdir dir, mode
rescue SystemCallError
raise unless File.directory?(dir)
end
end
end
return *list
end Создаёт каталоги по путям из заданного list (один путь или массив путей), при необходимости создавая также родительские каталоги; если это массив, возвращает list, в противном случае — [list].
Аргумент list или его элементы должны интерпретироваться как пути.
Если именованные аргументы не заданы, создаёт каталог для каждого path в list вместе со всеми необходимыми родительскими каталогами, вызывая: Dir.mkdir(path, mode); см. Dir.mkdir:
FileUtils.mkdir_p(%w[tmp0/tmp1 tmp2/tmp3]) # => ["tmp0/tmp1", "tmp2/tmp3"]
FileUtils.mkdir_p('tmp4/tmp5') # => ["tmp4/tmp5"]
Именованные аргументы:
-
mode: mode— также вызываетFile.chmod(mode, path); см.File.chmod. -
noop: true— не создаёт каталоги. -
verbose: true— выводит эквивалентную команду:FileUtils.mkdir_p(%w[tmp0 tmp1], verbose: true) FileUtils.mkdir_p(%w[tmp2 tmp3], mode: 0700, verbose: true)
Вывод:
mkdir -p tmp0 tmp1 mkdir -p -m 700 tmp2 tmp3
Вызывает исключение, если по какой-либо причине не удаётся создать каталог.
FileUtils.mkpath и FileUtils.makedirs — псевдонимы для FileUtils.mkdir_p.
Связанный метод: FileUtils.mkdir.
# File lib/fileutils.rb, line 1158
def mv(src, dest, force: nil, noop: nil, verbose: nil, secure: nil)
fu_output_message "mv#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose
return if noop
fu_each_src_dest(src, dest) do |s, d|
destent = Entry_.new(d, nil, true)
begin
if destent.exist?
if destent.directory?
raise Errno::EEXIST, d
end
end
begin
File.rename s, d
rescue Errno::EXDEV,
Errno::EPERM # move from unencrypted to encrypted dir (ext4)
copy_entry s, d, true
if secure
remove_entry_secure s, force
else
remove_entry s, force
end
end
rescue SystemCallError
raise unless force
end
end
end Перемещает элементы файловой системы.
Аргументы src (один путь или массив путей) и dest (один путь) должны интерпретироваться как пути.
Если src и dest находятся в разных файловых системах, сначала выполняет копирование, а затем удаляет src.
При вызове без именованного аргумента secure: true может возникнуть локальная уязвимость; см. Как избежать уязвимости TOCTTOU.
Если src — путь к одному файлу или каталогу, а dest не существует, перемещает src в dest:
tree('src0')
# => src0
# |-- src0.txt
# `-- src1.txt
File.exist?('dest0') # => false
FileUtils.mv('src0', 'dest0')
File.exist?('src0') # => false
tree('dest0')
# => dest0
# |-- src0.txt
# `-- src1.txt
Если src — массив путей к файлам и каталогам, а dest — путь к каталогу, копирует каждый путь из массива в dest:
File.file?('src1.txt') # => true
tree('src1')
# => src1
# |-- src.dat
# `-- src.txt
Dir.empty?('dest1') # => true
FileUtils.mv(['src1.txt', 'src1'], 'dest1')
tree('dest1')
# => dest1
# |-- src1
# | |-- src.dat
# | `-- src.txt
# `-- src1.txt
Именованные аргументы:
-
force: true— если перемещение включает удалениеsrc(то есть еслиsrcиdestнаходятся в разных файловых системах), игнорирует возникающие исключенияStandardErrorи его подклассов. -
noop: true— не перемещает файлы. -
secure: true— безопасно удаляетsrc; подробности см. в описанииFileUtils.remove_entry_secure. -
verbose: true— выводит эквивалентную команду:FileUtils.mv('src0', 'dest0', noop: true, verbose: true) FileUtils.mv(['src1.txt', 'src1'], 'dest1', noop: true, verbose: true)Вывод:
mv src0 dest0 mv src1.txt src1 dest1
# File lib/fileutils.rb, line 2580
def self.options
OPT_TABLE.values.flatten.uniq.map {|sym| sym.to_s }
end Возвращает массив строк с именами именованных аргументов:
FileUtils.options.take(3) # => ["noop", "verbose", "force"]
# File lib/fileutils.rb, line 2601
def self.options_of(mid)
OPT_TABLE[mid.to_s].map {|sym| sym.to_s }
end Возвращает массив строк с именами именованных аргументов метода mid; аргумент может быть строкой или символом:
FileUtils.options_of(:rm) # => ["force", "noop", "verbose"]
FileUtils.options_of('mv') # => ["force", "noop", "verbose", "secure"]
# File lib/fileutils.rb, line 198 def pwd Dir.pwd end
Возвращает строку с путём к текущему каталогу:
FileUtils.pwd # => "/rdoc/fileutils"
Связанный метод: FileUtils.cd.
# File lib/fileutils.rb, line 1493 def remove_dir(path, force = false) remove_entry path, force # FIXME?? check if it is a directory end
Рекурсивно удаляет элемент каталога, заданный аргументом path, который должен указывать на обычный файл, символическую ссылку или каталог.
Аргумент path должен интерпретироваться как путь.
Необязательный аргумент force указывает, следует ли игнорировать возникающие исключения StandardError и его подклассов.
Связанные методы: методы удаления.
# File lib/fileutils.rb, line 1450
def remove_entry(path, force = false)
Entry_.new(path).postorder_traverse do |ent|
begin
ent.remove
rescue
raise unless force
end
end
rescue
raise unless force
end Удаляет элемент, заданный аргументом path, который должен указывать на обычный файл, символическую ссылку или каталог.
Аргумент path должен интерпретироваться как путь.
Необязательный аргумент force указывает, следует ли игнорировать возникающие исключения StandardError и его подклассов.
Связанный метод: FileUtils.remove_entry_secure.
# File lib/fileutils.rb, line 1352
def remove_entry_secure(path, force = false)
unless fu_have_symlink?
remove_entry path, force
return
end
fullpath = File.expand_path(path)
st = File.lstat(fullpath)
unless st.directory?
File.unlink fullpath
return
end
# is a directory.
parent_st = File.stat(File.dirname(fullpath))
unless parent_st.world_writable?
remove_entry path, force
return
end
unless parent_st.sticky?
raise ArgumentError, "parent directory is world writable, FileUtils#remove_entry_secure does not work; abort: #{path.inspect} (parent directory mode #{'%o' % parent_st.mode})"
end
# freeze tree root
euid = Process.euid
dot_file = fullpath + "/."
begin
File.open(dot_file) {|f|
unless fu_stat_identical_entry?(st, f.stat)
# symlink (TOC-to-TOU attack?)
File.unlink fullpath
return
end
f.chown euid, -1
f.chmod 0700
}
rescue Errno::EISDIR # JRuby in non-native mode can't open files as dirs
File.lstat(dot_file).tap {|fstat|
unless fu_stat_identical_entry?(st, fstat)
# symlink (TOC-to-TOU attack?)
File.unlink fullpath
return
end
File.chown euid, -1, dot_file
File.chmod 0700, dot_file
}
end
unless fu_stat_identical_entry?(st, File.lstat(fullpath))
# TOC-to-TOU attack?
File.unlink fullpath
return
end
# ---- tree root is frozen ----
root = Entry_.new(path)
root.preorder_traverse do |ent|
if ent.directory?
ent.chown euid, -1
ent.chmod 0700
end
end
root.postorder_traverse do |ent|
begin
ent.remove
rescue
raise unless force
end
end
rescue
raise unless force
end Безопасно удаляет элемент, заданный аргументом path, который должен указывать на обычный файл, символическую ссылку или каталог.
Аргумент path должен интерпретироваться как путь.
Предотвращает локальную уязвимость, которая может возникнуть при определённых обстоятельствах; см. Как избежать уязвимости TOCTTOU.
Необязательный аргумент force указывает, следует ли игнорировать возникающие исключения StandardError и его подклассов.
Связанные методы: методы удаления.
# File lib/fileutils.rb, line 1474 def remove_file(path, force = false) Entry_.new(path).remove_file rescue raise unless force end
Удаляет файловый элемент, заданный аргументом path, который должен указывать на обычный файл или символическую ссылку.
Аргумент path должен интерпретироваться как путь.
Необязательный аргумент force указывает, следует ли игнорировать возникающие исключения StandardError и его подклассов.
Связанные методы: методы удаления.
# File lib/fileutils.rb, line 1217
def rm(list, force: nil, noop: nil, verbose: nil)
list = fu_list(list)
fu_output_message "rm#{force ? ' -f' : ''} #{list.join ' '}" if verbose
return if noop
list.each do |path|
remove_file path, force
end
end Удаляет элементы по путям из заданного list (один путь или массив путей); если это массив, возвращает list, в противном случае — [list].
Аргумент list или его элементы должны интерпретироваться как пути.
Если именованные аргументы не заданы, удаляет файлы по путям, указанным в list:
FileUtils.touch(['src0.txt', 'src0.dat']) FileUtils.rm(['src0.dat', 'src0.txt']) # => ["src0.dat", "src0.txt"]
Именованные аргументы:
-
force: true— игнорирует возникающие исключенияStandardErrorи его подклассов. -
noop: true— не удаляет файлы; возвращаетnil. -
verbose: true— выводит эквивалентную команду:FileUtils.rm(['src0.dat', 'src0.txt'], noop: true, verbose: true)
Вывод:
rm src0.dat src0.txt
Связанные методы: методы удаления.
# File lib/fileutils.rb, line 1242 def rm_f(list, noop: nil, verbose: nil) rm list, force: true, noop: noop, verbose: verbose end
Эквивалентно:
FileUtils.rm(list, force: true, **kwargs)
Аргумент list (один путь или массив путей) должен интерпретироваться как набор путей.
Именованные аргументы описаны в FileUtils.rm.
Связанные методы: методы удаления.
# File lib/fileutils.rb, line 1300
def rm_r(list, force: nil, noop: nil, verbose: nil, secure: nil)
list = fu_list(list)
fu_output_message "rm -r#{force ? 'f' : ''} #{list.join ' '}" if verbose
return if noop
list.each do |path|
if secure
remove_entry_secure path, force
else
remove_entry path, force
end
end
end Удаляет элементы по путям из заданного list (один путь или массив путей); если это массив, возвращает list, в противном случае — [list].
Аргумент list или его элементы должны интерпретироваться как пути.
При вызове без именованного аргумента secure: true может возникнуть локальная уязвимость; см. Как избежать уязвимости TOCTTOU.
Для каждого пути к файлу удаляет файл по этому пути:
FileUtils.touch(['src0.txt', 'src0.dat'])
FileUtils.rm_r(['src0.dat', 'src0.txt'])
File.exist?('src0.txt') # => false
File.exist?('src0.dat') # => false
Для каждого пути к каталогу рекурсивно удаляет файлы и каталоги:
tree('src1')
# => src1
# |-- dir0
# | |-- src0.txt
# | `-- src1.txt
# `-- dir1
# |-- src2.txt
# `-- src3.txt
FileUtils.rm_r('src1')
File.exist?('src1') # => false
Именованные аргументы:
-
force: true— игнорирует возникающие исключенияStandardErrorи его подклассов. -
noop: true— не удаляет элементы; возвращаетnil. -
secure: true— безопасно удаляетsrc; подробности см. в описанииFileUtils.remove_entry_secure. -
verbose: true— выводит эквивалентную команду:FileUtils.rm_r(['src0.dat', 'src0.txt'], noop: true, verbose: true) FileUtils.rm_r('src1', noop: true, verbose: true)Вывод:
rm -r src0.dat src0.txt rm -r src1
Связанные методы: методы удаления.
# File lib/fileutils.rb, line 1329 def rm_rf(list, noop: nil, verbose: nil, secure: nil) rm_r list, force: true, noop: noop, verbose: verbose, secure: secure end
Эквивалентно:
FileUtils.rm_r(list, force: true, **kwargs)
Аргумент list или его элементы должны интерпретироваться как пути.
При вызове без именованного аргумента secure: true может возникнуть локальная уязвимость; см. Как избежать уязвимости TOCTTOU.
Именованные аргументы описаны в FileUtils.rm_r.
Связанные методы: методы удаления.
# File lib/fileutils.rb, line 443
def rmdir(list, parents: nil, noop: nil, verbose: nil)
list = fu_list(list)
fu_output_message "rmdir #{parents ? '-p ' : ''}#{list.join ' '}" if verbose
return if noop
list.each do |dir|
Dir.rmdir(dir = remove_trailing_slash(dir))
if parents
begin
until (parent = File.dirname(dir)) == '.' or parent == dir
dir = parent
Dir.rmdir(dir)
end
rescue Errno::ENOTEMPTY, Errno::EEXIST, Errno::ENOENT
end
end
end
end Удаляет каталоги по путям из заданного list (один путь или массив путей); если это массив, возвращает list, в противном случае — [list].
Аргумент list или его элементы должны интерпретироваться как пути.
Если именованные аргументы не заданы, удаляет каталог для каждого path в list, вызывая: Dir.rmdir(path); см. Dir.rmdir:
FileUtils.rmdir(%w[tmp0/tmp1 tmp2/tmp3]) # => ["tmp0/tmp1", "tmp2/tmp3"]
FileUtils.rmdir('tmp4/tmp5') # => ["tmp4/tmp5"]
Именованные аргументы:
-
parents: true— удаляет последовательно родительские каталоги, если они пусты. -
noop: true— не удаляет каталоги. -
verbose: true— выводит эквивалентную команду:FileUtils.rmdir(%w[tmp0/tmp1 tmp2/tmp3], parents: true, verbose: true) FileUtils.rmdir('tmp4/tmp5', parents: true, verbose: true)Вывод:
rmdir -p tmp0/tmp1 tmp2/tmp3 rmdir -p tmp4/tmp5
Вызывает исключение, если каталог не существует или если по какой-либо причине не удаётся удалить каталог.
Связанные методы: методы удаления.
# File lib/fileutils.rb, line 2007
def touch(list, noop: nil, verbose: nil, mtime: nil, nocreate: nil)
list = fu_list(list)
t = mtime
if verbose
fu_output_message "touch #{nocreate ? '-c ' : ''}#{t ? t.strftime('-t %Y%m%d%H%M.%S ') : ''}#{list.join ' '}"
end
return if noop
list.each do |path|
created = nocreate
begin
File.utime(t, t, path)
rescue Errno::ENOENT
raise if created
File.open(path, 'a') {
;
}
created = true
retry if t
end
end
end Обновляет время изменения (mtime) и время доступа (atime) элементов, заданных путями в list (один путь или массив путей); если это массив, возвращает list, в противном случае — [list].
По умолчанию для любого пути к несуществующему элементу создаёт пустой файл; чтобы вместо этого вызвать исключение, используйте именованный аргумент nocreate.
Аргумент list или его элементы должны интерпретироваться как пути.
Примеры:
# Single path.
f = File.new('src0.txt') # Existing file.
f.atime # => 2022-06-10 11:11:21.200277 -0700
f.mtime # => 2022-06-10 11:11:21.200277 -0700
FileUtils.touch('src0.txt')
f = File.new('src0.txt')
f.atime # => 2022-06-11 08:28:09.8185343 -0700
f.mtime # => 2022-06-11 08:28:09.8185343 -0700
# Array of paths.
FileUtils.touch(['src0.txt', 'src0.dat'])
Именованные аргументы:
-
mtime: time— задаёт для элемента указанное время mtime вместо текущего времени. -
nocreate: true— вызывает исключение, если элемент не существует. -
noop: true— не изменяет временные метки элементов; возвращаетnil. -
verbose: true— выводит эквивалентную команду:FileUtils.touch('src0.txt', noop: true, verbose: true) FileUtils.touch(['src0.txt', 'src0.dat'], noop: true, verbose: true) FileUtils.touch(path, noop: true, verbose: true)Вывод:
touch src0.txt touch src0.txt src0.dat touch src0.txt
Связанный метод: FileUtils.uptodate?.
# File lib/fileutils.rb, line 265
def uptodate?(new, old_list)
return false unless File.exist?(new)
new_time = File.mtime(new)
old_list.each do |old|
if File.exist?(old)
return false unless new_time > File.mtime(old)
end
end
true
end Возвращает true, если файл по пути new новее всех файлов по путям в массиве old_list; в противном случае возвращает false.
Аргумент new и элементы old_list должны быть интерпретируемы как пути:
FileUtils.uptodate?('Rakefile', ['Gemfile', 'README.md']) # => true
FileUtils.uptodate?('Gemfile', ['Rakefile', 'README.md']) # => false
Считается, что несуществующий файл бесконечно стар.
Связанный метод: FileUtils.touch.
Приватные методы экземпляра
# File lib/fileutils.rb, line 239
def cd(dir, verbose: nil, &block) # :yield: dir
fu_output_message "cd #{dir}" if verbose
result = Dir.chdir(dir, &block)
fu_output_message 'cd -' if verbose and block
result
end Изменяет рабочий каталог на указанный dir, который должен быть интерпретируем как путь:
Если блок не указан, изменяет текущий каталог на каталог по пути dir; возвращает ноль:
FileUtils.pwd # => "/rdoc/fileutils"
FileUtils.cd('..')
FileUtils.pwd # => "/rdoc"
FileUtils.cd('fileutils')
Если блок указан, изменяет текущий каталог на каталог по пути dir, вызывает блок с аргументом dir и восстанавливает исходный текущий каталог; возвращает значение блока:
FileUtils.pwd # => "/rdoc/fileutils"
FileUtils.cd('..') { |arg| [arg, FileUtils.pwd] } # => ["..", "/rdoc"]
FileUtils.pwd # => "/rdoc/fileutils"
Именованные аргументы:
-
verbose: true— выводит эквивалентную команду:FileUtils.cd('..') FileUtils.cd('fileutils')Вывод:
cd .. cd fileutils
Связанный метод: FileUtils.pwd.
# File lib/fileutils.rb, line 1804
def chmod(mode, list, noop: nil, verbose: nil)
list = fu_list(list)
fu_output_message sprintf('chmod %s %s', mode_to_s(mode), list.join(' ')) if verbose
return if noop
list.each do |path|
Entry_.new(path).chmod(fu_mode(mode, path))
end
end Изменяет права доступа для элементов по путям, указанным в list (один путь или массив путей), на права, заданные в mode; возвращает list, если это массив, и [list] в противном случае:
-
Изменяет каждый элемент, являющийся обычным файлом, с помощью
File.chmod. -
Изменяет каждый элемент, являющийся символической ссылкой, с помощью
File.lchmod.
Аргумент list или его элементы должны быть интерпретируемы как пути.
Аргумент mode может быть целым числом или строкой:
-
Целое число
mode: обозначает устанавливаемые биты прав доступа:FileUtils.chmod(0755, 'src0.txt') FileUtils.chmod(0644, ['src0.txt', 'src0.dat'])
-
Строка
mode: обозначает устанавливаемые права доступа:Строка имеет вид
[targets][[operator][perms[,perms]], где:-
targetsможет содержать любую комбинацию следующих букв:-
'u': права доступа применяются к владельцу файла. -
'g': права доступа применяются к пользователям из группы файла. -
'o': права доступа применяются к другим пользователям, не входящим в группу файла. -
'a'(по умолчанию): права доступа применяются ко всем пользователям.
-
-
operatorможет быть одной из следующих букв:-
'+': добавляет права доступа. -
'-': удаляет права доступа. -
'=': устанавливает (заменяет) права доступа.
-
-
perms(может повторяться; элементы разделяются запятыми) может содержать любую комбинацию следующих букв:-
'r': чтение. -
'w': запись. -
'x': выполнение (поиск для каталога). -
'X': поиск (только для каталогов; должно использоваться вместе с'+') -
's': UID или GID. -
't': бит фиксации (sticky bit).
-
Примеры:
FileUtils.chmod('u=wrx,go=rx', 'src1.txt') FileUtils.chmod('u=wrx,go=rx', '/usr/bin/ruby') -
Именованные аргументы:
-
noop: true— не изменяет права доступа; возвращаетnil. -
verbose: true— выводит эквивалентную команду:FileUtils.chmod(0755, 'src0.txt', noop: true, verbose: true) FileUtils.chmod(0644, ['src0.txt', 'src0.dat'], noop: true, verbose: true) FileUtils.chmod('u=wrx,go=rx', 'src1.txt', noop: true, verbose: true) FileUtils.chmod('u=wrx,go=rx', '/usr/bin/ruby', noop: true, verbose: true)Вывод:
chmod 755 src0.txt chmod 644 src0.txt src0.dat chmod u=wrx,go=rx src1.txt chmod u=wrx,go=rx /usr/bin/ruby
Связанный метод: FileUtils.chmod_R.
# File lib/fileutils.rb, line 1816
def chmod_R(mode, list, noop: nil, verbose: nil, force: nil)
list = fu_list(list)
fu_output_message sprintf('chmod -R%s %s %s',
(force ? 'f' : ''),
mode_to_s(mode), list.join(' ')) if verbose
return if noop
list.each do |root|
Entry_.new(root).traverse do |ent|
begin
ent.chmod(fu_mode(mode, ent.path))
rescue
raise unless force
end
end
end
end Как FileUtils.chmod, но рекурсивно изменяет права доступа.
# File lib/fileutils.rb, line 1897
def chown(user, group, list, noop: nil, verbose: nil)
list = fu_list(list)
fu_output_message sprintf('chown %s %s',
(group ? "#{user}:#{group}" : user || ':'),
list.join(' ')) if verbose
return if noop
uid = fu_get_uid(user)
gid = fu_get_gid(group)
list.each do |path|
Entry_.new(path).chown uid, gid
end
end Изменяет владельца и группу элементов по путям, указанным в list (один путь или массив путей), на заданные user и group; возвращает list, если это массив, и [list] в противном случае:
-
Изменяет каждый элемент, являющийся обычным файлом, с помощью
File.chown. -
Изменяет каждый элемент, являющийся символической ссылкой, с помощью
File.lchown.
Аргумент list или его элементы должны быть интерпретируемы как пути.
Пользователь и группа:
-
Аргумент
userможет быть именем пользователя или его идентификатором; если указаноnilили-1, пользователь не изменяется. -
Аргумент
groupможет быть именем группы или её идентификатором; если указаноnilили-1, группа не изменяется. -
Пользователь должен входить в эту группу.
Примеры:
# One path.
# User and group as string names.
File.stat('src0.txt').uid # => 1004
File.stat('src0.txt').gid # => 1004
FileUtils.chown('user2', 'group1', 'src0.txt')
File.stat('src0.txt').uid # => 1006
File.stat('src0.txt').gid # => 1005
# User and group as uid and gid.
FileUtils.chown(1004, 1004, 'src0.txt')
File.stat('src0.txt').uid # => 1004
File.stat('src0.txt').gid # => 1004
# Array of paths.
FileUtils.chown(1006, 1005, ['src0.txt', 'src0.dat'])
# Directory (not recursive).
FileUtils.chown('user2', 'group1', '.')
Именованные аргументы:
-
noop: true— не изменяет права доступа; возвращаетnil. -
verbose: true— выводит эквивалентную команду:FileUtils.chown('user2', 'group1', 'src0.txt', noop: true, verbose: true) FileUtils.chown(1004, 1004, 'src0.txt', noop: true, verbose: true) FileUtils.chown(1006, 1005, ['src0.txt', 'src0.dat'], noop: true, verbose: true) FileUtils.chown('user2', 'group1', path, noop: true, verbose: true) FileUtils.chown('user2', 'group1', '.', noop: true, verbose: true)Вывод:
chown user2:group1 src0.txt chown 1004:1004 src0.txt chown 1006:1005 src0.txt src0.dat chown user2:group1 src0.txt chown user2:group1 .
Связанный метод: FileUtils.chown_R.
# File lib/fileutils.rb, line 1913
def chown_R(user, group, list, noop: nil, verbose: nil, force: nil)
list = fu_list(list)
fu_output_message sprintf('chown -R%s %s %s',
(force ? 'f' : ''),
(group ? "#{user}:#{group}" : user || ':'),
list.join(' ')) if verbose
return if noop
uid = fu_get_uid(user)
gid = fu_get_gid(group)
list.each do |root|
Entry_.new(root).traverse do |ent|
begin
ent.chown uid, gid
rescue
raise unless force
end
end
end
end Как FileUtils.chown, но рекурсивно изменяет владельца и группу.
# File lib/fileutils.rb, line 1508
def compare_file(a, b)
return false unless File.size(a) == File.size(b)
File.open(a, 'rb') {|fa|
File.open(b, 'rb') {|fb|
return compare_stream(fa, fb)
}
}
end Возвращает true, если содержимое файлов a и b идентично, и false в противном случае.
Аргументы a и b должны быть интерпретируемы как путь.
FileUtils.identical? и FileUtils.cmp — псевдонимы для FileUtils.compare_file.
Связанный метод: FileUtils.compare_stream.
# File lib/fileutils.rb, line 1531
def compare_stream(a, b)
bsize = fu_stream_blksize(a, b)
sa = String.new(capacity: bsize)
sb = String.new(capacity: bsize)
begin
a.read(bsize, sa)
b.read(bsize, sb)
return true if sa.empty? && sb.empty?
end while sa == sb
false
end Возвращает true, если содержимое потоков a и b идентично, и false в противном случае.
Аргументы a и b должны быть интерпретируемы как путь.
Связанный метод: FileUtils.compare_file.
# File lib/fileutils.rb, line 1041
def copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false)
if dereference_root
src = File.realpath(src)
end
Entry_.new(src, nil, false).wrap_traverse(proc do |ent|
destent = Entry_.new(dest, ent.rel, false)
File.unlink destent.path if remove_destination && (File.file?(destent.path) || File.symlink?(destent.path))
ent.copy destent.path
end, proc do |ent|
destent = Entry_.new(dest, ent.rel, false)
ent.copy_metadata destent.path if preserve
end)
end Рекурсивно копирует файлы из src в dest.
Аргументы src и dest должны быть интерпретируемы как пути.
Если src — путь к файлу, копирует src в dest:
FileUtils.touch('src0.txt')
File.exist?('dest0.txt') # => false
FileUtils.copy_entry('src0.txt', 'dest0.txt')
File.file?('dest0.txt') # => true
Если src — каталог, рекурсивно копирует src в dest:
tree('src1')
# => src1
# |-- dir0
# | |-- src0.txt
# | `-- src1.txt
# `-- dir1
# |-- src2.txt
# `-- src3.txt
FileUtils.copy_entry('src1', 'dest1')
tree('dest1')
# => dest1
# |-- dir0
# | |-- src0.txt
# | `-- src1.txt
# `-- dir1
# |-- src2.txt
# `-- src3.txt
При рекурсивном копировании сохраняются типы обычных файлов, каталогов и символических ссылок; другие типы файлов (потоки FIFO, файлы устройств и т. д.) не поддерживаются.
Именованные аргументы:
-
dereference_root: true— еслиsrcявляется символической ссылкой, переходит по ней. -
preserve: true— сохраняет время файлов. -
remove_destination: true— удаляетdestперед копированием файлов.
Связанные методы: методы копирования.
# File lib/fileutils.rb, line 1077 def copy_file(src, dest, preserve = false, dereference = true) ent = Entry_.new(src, nil, dereference) ent.copy_file dest ent.copy_metadata dest if preserve end
Копирует файл из src в dest; они не должны быть каталогами.
Аргументы src и dest должны быть интерпретируемы как пути.
Примеры:
FileUtils.touch('src0.txt')
FileUtils.copy_file('src0.txt', 'dest0.txt')
File.file?('dest0.txt') # => true
Именованные аргументы:
-
dereference: false— еслиsrcявляется символической ссылкой, не переходит по ней. -
preserve: true— сохраняет время файлов. -
remove_destination: true— удаляетdestперед копированием файлов.
Связанные методы: методы копирования.
# File lib/fileutils.rb, line 1089 def copy_stream(src, dest) IO.copy_stream(src, dest) end
Копирует поток ввода-вывода src в поток ввода-вывода dest с помощью IO.copy_stream.
Связанные методы: методы копирования.
# File lib/fileutils.rb, line 874
def cp(src, dest, preserve: nil, noop: nil, verbose: nil)
fu_output_message "cp#{preserve ? ' -p' : ''} #{[src,dest].flatten.join ' '}" if verbose
return if noop
fu_each_src_dest(src, dest) do |s, d|
copy_file s, d, preserve
end
end Копирует файлы.
Аргументы src (один путь или массив путей) и dest (один путь) должны быть интерпретируемы как пути.
Если src — путь к файлу, а dest не является путём к каталогу, копирует src в dest:
FileUtils.touch('src0.txt')
File.exist?('dest0.txt') # => false
FileUtils.cp('src0.txt', 'dest0.txt')
File.file?('dest0.txt') # => true
Если src — путь к файлу, а dest — путь к каталогу, копирует src в dest/src:
FileUtils.touch('src1.txt')
FileUtils.mkdir('dest1')
FileUtils.cp('src1.txt', 'dest1')
File.file?('dest1/src1.txt') # => true
Если src — массив путей к файлам, а dest — путь к каталогу, копирует каждый src в dest:
src_file_paths = ['src2.txt', 'src2.dat']
FileUtils.touch(src_file_paths)
FileUtils.mkdir('dest2')
FileUtils.cp(src_file_paths, 'dest2')
File.file?('dest2/src2.txt') # => true
File.file?('dest2/src2.dat') # => true
Именованные аргументы:
-
preserve: true— сохраняет время файлов. -
noop: true— не копирует файлы. -
verbose: true— выводит эквивалентную команду:FileUtils.cp('src0.txt', 'dest0.txt', noop: true, verbose: true) FileUtils.cp('src1.txt', 'dest1', noop: true, verbose: true) FileUtils.cp(src_file_paths, 'dest2', noop: true, verbose: true)Вывод:
cp src0.txt dest0.txt cp src1.txt dest1 cp src2.txt src2.dat dest2
Вызывает исключение, если src является каталогом.
Связанные методы: методы копирования.
# File lib/fileutils.rb, line 628
def cp_lr(src, dest, noop: nil, verbose: nil,
dereference_root: true, remove_destination: false)
fu_output_message "cp -lr#{remove_destination ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if verbose
return if noop
fu_each_src_dest(src, dest) do |s, d|
link_entry s, d, dereference_root, remove_destination
end
end Создаёт жёсткие ссылки.
Аргументы src (один путь или массив путей) и dest (один путь) должны быть интерпретируемы как пути.
Если src — путь к каталогу, а dest не существует, создаёт ссылки dest и его содержимого, указывающие на src и его содержимое:
tree('src0')
# => src0
# |-- sub0
# | |-- src0.txt
# | `-- src1.txt
# `-- sub1
# |-- src2.txt
# `-- src3.txt
File.exist?('dest0') # => false
FileUtils.cp_lr('src0', 'dest0')
tree('dest0')
# => dest0
# |-- sub0
# | |-- src0.txt
# | `-- src1.txt
# `-- sub1
# |-- src2.txt
# `-- src3.txt
Если src и dest являются путями к каталогам, создаёт ссылки dest/src и его содержимого, указывающие на src и его содержимое:
tree('src1')
# => src1
# |-- sub0
# | |-- src0.txt
# | `-- src1.txt
# `-- sub1
# |-- src2.txt
# `-- src3.txt
FileUtils.mkdir('dest1')
FileUtils.cp_lr('src1', 'dest1')
tree('dest1')
# => dest1
# `-- src1
# |-- sub0
# | |-- src0.txt
# | `-- src1.txt
# `-- sub1
# |-- src2.txt
# `-- src3.txt
Если src — массив путей к элементам, а dest — путь к каталогу, для каждого пути filepath в src создаёт ссылку по пути dest/filepath, указывающую на этот путь:
tree('src2')
# => src2
# |-- sub0
# | |-- src0.txt
# | `-- src1.txt
# `-- sub1
# |-- src2.txt
# `-- src3.txt
FileUtils.mkdir('dest2')
FileUtils.cp_lr(['src2/sub0', 'src2/sub1'], 'dest2')
tree('dest2')
# => dest2
# |-- sub0
# | |-- src0.txt
# | `-- src1.txt
# `-- sub1
# |-- src2.txt
# `-- src3.txt
Именованные аргументы:
-
dereference_root: false— еслиsrcявляется символической ссылкой, не переходит по ней. -
noop: true— не создаёт ссылки. -
remove_destination: true— удаляетdestперед созданием ссылок. -
verbose: true— выводит эквивалентную команду:FileUtils.cp_lr('src0', 'dest0', noop: true, verbose: true) FileUtils.cp_lr('src1', 'dest1', noop: true, verbose: true) FileUtils.cp_lr(['src2/sub0', 'src2/sub1'], 'dest2', noop: true, verbose: true)Вывод:
cp -lr src0 dest0 cp -lr src1 dest1 cp -lr src2/sub0 src2/sub1 dest2
Вызывает исключение, если dest — путь к существующему файлу или каталогу и не указан именованный аргумент remove_destination: true.
Связанные методы: методы копирования.
# File lib/fileutils.rb, line 986
def cp_r(src, dest, preserve: nil, noop: nil, verbose: nil,
dereference_root: true, remove_destination: nil)
fu_output_message "cp -r#{preserve ? 'p' : ''}#{remove_destination ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if verbose
return if noop
fu_each_src_dest(src, dest) do |s, d|
copy_entry s, d, preserve, dereference_root, remove_destination
end
end Рекурсивно копирует файлы.
Аргументы src (один путь или массив путей) и dest (один путь) должны быть интерпретируемы как пути.
Режим доступа, владелец и группа сохраняются при копировании; чтобы изменить их, используйте FileUtils.install.
Если src — путь к файлу, а dest не является путём к каталогу, копирует src в dest:
FileUtils.touch('src0.txt')
File.exist?('dest0.txt') # => false
FileUtils.cp_r('src0.txt', 'dest0.txt')
File.file?('dest0.txt') # => true
Если src — путь к файлу, а dest — путь к каталогу, копирует src в dest/src:
FileUtils.touch('src1.txt')
FileUtils.mkdir('dest1')
FileUtils.cp_r('src1.txt', 'dest1')
File.file?('dest1/src1.txt') # => true
Если src — путь к каталогу, а dest не существует, рекурсивно копирует src в dest:
tree('src2')
# => src2
# |-- dir0
# | |-- src0.txt
# | `-- src1.txt
# `-- dir1
# |-- src2.txt
# `-- src3.txt
FileUtils.exist?('dest2') # => false
FileUtils.cp_r('src2', 'dest2')
tree('dest2')
# => dest2
# |-- dir0
# | |-- src0.txt
# | `-- src1.txt
# `-- dir1
# |-- src2.txt
# `-- src3.txt
Если src и dest являются путями к каталогам, рекурсивно копирует src в dest/src:
tree('src3')
# => src3
# |-- dir0
# | |-- src0.txt
# | `-- src1.txt
# `-- dir1
# |-- src2.txt
# `-- src3.txt
FileUtils.mkdir('dest3')
FileUtils.cp_r('src3', 'dest3')
tree('dest3')
# => dest3
# `-- src3
# |-- dir0
# | |-- src0.txt
# | `-- src1.txt
# `-- dir1
# |-- src2.txt
# `-- src3.txt
Если src — массив путей, а dest — каталог, рекурсивно копирует каждый путь из src в dest; пути в src могут указывать на файлы и/или каталоги.
Именованные аргументы:
-
dereference_root: false— еслиsrcявляется символической ссылкой, не переходит по ней. -
noop: true— не копирует файлы. -
preserve: true— сохраняет время файлов. -
remove_destination: true— удаляетdestперед копированием файлов. -
verbose: true— выводит эквивалентную команду:FileUtils.cp_r('src0.txt', 'dest0.txt', noop: true, verbose: true) FileUtils.cp_r('src1.txt', 'dest1', noop: true, verbose: true) FileUtils.cp_r('src2', 'dest2', noop: true, verbose: true) FileUtils.cp_r('src3', 'dest3', noop: true, verbose: true)Вывод:
cp -r src0.txt dest0.txt cp -r src1.txt dest1 cp -r src2 dest2 cp -r src3 dest3
Вызывает исключение, если src — путь к каталогу, а dest — путь к файлу.
Связанные методы: методы копирования.
# File lib/fileutils.rb, line 1610
def install(src, dest, mode: nil, owner: nil, group: nil, preserve: nil,
noop: nil, verbose: nil)
if verbose
msg = +"install -c"
msg << ' -p' if preserve
msg << ' -m ' << mode_to_s(mode) if mode
msg << " -o #{owner}" if owner
msg << " -g #{group}" if group
msg << ' ' << [src,dest].flatten.join(' ')
fu_output_message msg
end
return if noop
uid = fu_get_uid(owner)
gid = fu_get_gid(group)
fu_each_src_dest(src, dest) do |s, d|
st = File.stat(s)
unless File.exist?(d) and compare_file(s, d)
remove_file d, true
if d.end_with?('/')
mkdir_p d
copy_file s, d + File.basename(s)
else
mkdir_p File.expand_path('..', d)
copy_file s, d
end
File.utime st.atime, st.mtime, d if preserve
File.chmod fu_mode(mode, st), d if mode
File.chown uid, gid, d if uid or gid
end
end
end Копирует файловый элемент. См. install(1).
Аргументы src (один путь или массив путей) и dest (один путь) должны быть интерпретируемы как пути;
Если элемент по пути dest не существует, копирует из src в dest:
File.read('src0.txt') # => "aaa\n"
File.exist?('dest0.txt') # => false
FileUtils.install('src0.txt', 'dest0.txt')
File.read('dest0.txt') # => "aaa\n"
Если dest — файловый элемент, копирует из src в dest с перезаписью:
File.read('src1.txt') # => "aaa\n"
File.read('dest1.txt') # => "bbb\n"
FileUtils.install('src1.txt', 'dest1.txt')
File.read('dest1.txt') # => "aaa\n"
Если dest — элемент-каталог, копирует из src в dest/src, при необходимости выполняя перезапись:
File.read('src2.txt') # => "aaa\n"
File.read('dest2/src2.txt') # => "bbb\n"
FileUtils.install('src2.txt', 'dest2')
File.read('dest2/src2.txt') # => "aaa\n"
Если src — массив путей, а dest указывает на каталог, копирует каждый путь path из src в dest/path:
File.file?('src3.txt') # => true
File.file?('src3.dat') # => true
FileUtils.mkdir('dest3')
FileUtils.install(['src3.txt', 'src3.dat'], 'dest3')
File.file?('dest3/src3.txt') # => true
File.file?('dest3/src3.dat') # => true
Именованные аргументы:
-
group: group— изменяет группу, если она не равнаnil, с помощьюFile.chown. -
mode: permissions— изменяет права доступа с помощьюFile.chmod. -
noop: true— не копирует элементы; возвращаетnil. -
owner: owner— изменяет владельца, если он не равенnil, с помощьюFile.chown. -
preserve: true— сохраняет временные метки с помощьюFile.utime. -
verbose: true— выводит эквивалентную команду:FileUtils.install('src0.txt', 'dest0.txt', noop: true, verbose: true) FileUtils.install('src1.txt', 'dest1.txt', noop: true, verbose: true) FileUtils.install('src2.txt', 'dest2', noop: true, verbose: true)Вывод:
install -c src0.txt dest0.txt install -c src1.txt dest1.txt install -c src2.txt dest2
Связанные методы: методы копирования.
# File lib/fileutils.rb, line 813
def link_entry(src, dest, dereference_root = false, remove_destination = false)
Entry_.new(src, nil, dereference_root).traverse do |ent|
destent = Entry_.new(dest, ent.rel, false)
File.unlink destent.path if remove_destination && File.file?(destent.path)
ent.link destent.path
end
end Создаёт жёсткие ссылки; возвращает nil.
Аргументы src и dest должны быть интерпретируемы как пути.
Если src — путь к файлу, а dest не существует, создаёт жёсткую ссылку по пути dest, указывающую на src:
FileUtils.touch('src0.txt')
File.exist?('dest0.txt') # => false
FileUtils.link_entry('src0.txt', 'dest0.txt')
File.file?('dest0.txt') # => true
Если src — путь к каталогу, а dest не существует, рекурсивно создаёт жёсткие ссылки по путям dest, указывающие на пути в src:
FileUtils.mkdir_p(['src1/dir0', 'src1/dir1'])
src_file_paths = [
'src1/dir0/t0.txt',
'src1/dir0/t1.txt',
'src1/dir1/t2.txt',
'src1/dir1/t3.txt',
]
FileUtils.touch(src_file_paths)
File.directory?('dest1') # => true
FileUtils.link_entry('src1', 'dest1')
File.file?('dest1/dir0/t0.txt') # => true
File.file?('dest1/dir0/t1.txt') # => true
File.file?('dest1/dir1/t2.txt') # => true
File.file?('dest1/dir1/t3.txt') # => true
Именованные аргументы:
-
dereference_root: true— переходит поsrc, если это символическая ссылка. -
remove_destination: true— удаляетdestперед созданием ссылок.
Вызывает исключение, если dest — путь к существующему файлу или каталогу и не указан именованный аргумент remove_destination: true.
Связанный метод: FileUtils.ln (имеет другие параметры).
# File lib/fileutils.rb, line 517
def ln(src, dest, force: nil, noop: nil, verbose: nil)
fu_output_message "ln#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose
return if noop
fu_each_src_dest0(src, dest) do |s,d|
remove_file d, true if force
File.link s, d
end
end Создаёт жёсткие ссылки.
Аргументы src (один путь или массив путей) и dest (один путь) должны быть интерпретируемы как пути.
Если src — путь к существующему файлу, а dest — путь к несуществующему файлу, создаёт жёсткую ссылку по пути dest, указывающую на src; возвращает ноль:
Dir.children('tmp0/') # => ["t.txt"]
Dir.children('tmp1/') # => []
FileUtils.ln('tmp0/t.txt', 'tmp1/t.lnk') # => 0
Dir.children('tmp1/') # => ["t.lnk"]
Если src — путь к существующему файлу, а dest — путь к существующему каталогу, создаёт жёсткую ссылку по пути dest/src, указывающую на src; возвращает ноль:
Dir.children('tmp2') # => ["t.dat"]
Dir.children('tmp3') # => []
FileUtils.ln('tmp2/t.dat', 'tmp3') # => 0
Dir.children('tmp3') # => ["t.dat"]
Если src — массив путей к существующим файлам, а dest — путь к существующему каталогу, то для каждого пути target в src создаёт жёсткую ссылку по пути dest/target, указывающую на target; возвращает src:
Dir.children('tmp4/') # => []
FileUtils.ln(['tmp0/t.txt', 'tmp2/t.dat'], 'tmp4/') # => ["tmp0/t.txt", "tmp2/t.dat"]
Dir.children('tmp4/') # => ["t.dat", "t.txt"]
Именованные аргументы:
-
force: true— перезаписываетdest, если он существует. -
noop: true— не создаёт ссылки. -
verbose: true— выводит эквивалентную команду:FileUtils.ln('tmp0/t.txt', 'tmp1/t.lnk', verbose: true) FileUtils.ln('tmp2/t.dat', 'tmp3', verbose: true) FileUtils.ln(['tmp0/t.txt', 'tmp2/t.dat'], 'tmp4/', verbose: true)Вывод:
ln tmp0/t.txt tmp1/t.lnk ln tmp2/t.dat tmp3 ln tmp0/t.txt tmp2/t.dat tmp4/
Вызывает исключение, если dest — путь к существующему файлу, а именованный аргумент force не равен true.
Связанный метод: FileUtils.link_entry (имеет другие параметры).
# File lib/fileutils.rb, line 707
def ln_s(src, dest, force: nil, relative: false, target_directory: true, noop: nil, verbose: nil)
if relative
return ln_sr(src, dest, force: force, noop: noop, verbose: verbose)
end
fu_output_message "ln -s#{force ? 'f' : ''} #{[src,dest].flatten.join ' '}" if verbose
return if noop
fu_each_src_dest0(src, dest) do |s,d|
remove_file d, true if force
File.symlink s, d
end
end Создаёт символические ссылки.
Аргументы src (один путь или массив путей) и dest (один путь) должны быть интерпретируемы как пути.
Если src — путь к существующему файлу:
-
Если
dest— путь к несуществующему файлу, создаёт символическую ссылку по путиdest, указывающую наsrc:FileUtils.touch('src0.txt') File.exist?('dest0.txt') # => false FileUtils.ln_s('src0.txt', 'dest0.txt') File.symlink?('dest0.txt') # => true -
Если
dest— путь к существующему файлу, создаёт символическую ссылку по путиdest, указывающую наsrc, только если передан именованный аргументforce: true(иначе вызывает исключение):FileUtils.touch('src1.txt') FileUtils.touch('dest1.txt') FileUtils.ln_s('src1.txt', 'dest1.txt', force: true) FileTest.symlink?('dest1.txt') # => true FileUtils.ln_s('src1.txt', 'dest1.txt') # Raises Errno::EEXIST.
Если dest — путь к каталогу, создаёт символическую ссылку по пути dest/src, указывающую на src:
FileUtils.touch('src2.txt')
FileUtils.mkdir('destdir2')
FileUtils.ln_s('src2.txt', 'destdir2')
File.symlink?('destdir2/src2.txt') # => true
Если src — массив путей к существующим файлам, а dest — каталог, для каждого дочернего элемента child в src создаёт символическую ссылку dest/child, указывающую на child:
FileUtils.mkdir('srcdir3')
FileUtils.touch('srcdir3/src0.txt')
FileUtils.touch('srcdir3/src1.txt')
FileUtils.mkdir('destdir3')
FileUtils.ln_s(['srcdir3/src0.txt', 'srcdir3/src1.txt'], 'destdir3')
File.symlink?('destdir3/src0.txt') # => true
File.symlink?('destdir3/src1.txt') # => true
Именованные аргументы:
-
force: true— перезаписываетdest, если он существует. -
relative: false— создаёт ссылки относительноdest. -
noop: true— не создаёт ссылки. -
verbose: true— выводит эквивалентную команду:FileUtils.ln_s('src0.txt', 'dest0.txt', noop: true, verbose: true) FileUtils.ln_s('src1.txt', 'destdir1', noop: true, verbose: true) FileUtils.ln_s('src2.txt', 'dest2.txt', force: true, noop: true, verbose: true) FileUtils.ln_s(['srcdir3/src0.txt', 'srcdir3/src1.txt'], 'destdir3', noop: true, verbose: true)Вывод:
ln -s src0.txt dest0.txt ln -s src1.txt destdir1 ln -sf src2.txt dest2.txt ln -s srcdir3/src0.txt srcdir3/src1.txt destdir3
Связанный метод: FileUtils.ln_sf.
# File lib/fileutils.rb, line 725 def ln_sf(src, dest, noop: nil, verbose: nil) ln_s src, dest, force: true, noop: noop, verbose: verbose end
Как FileUtils.ln_s, но именованный аргумент force: true передаётся всегда.
# File lib/fileutils.rb, line 732
def ln_sr(src, dest, target_directory: true, force: nil, noop: nil, verbose: nil)
options = "#{force ? 'f' : ''}#{target_directory ? '' : 'T'}"
dest = File.path(dest)
srcs = Array(src)
link = proc do |s, target_dir_p = true|
s = File.path(s)
if target_dir_p
d = File.join(destdirs = dest, File.basename(s))
else
destdirs = File.dirname(d = dest)
end
destdirs = fu_split_path(File.realpath(destdirs))
if fu_starting_path?(s)
srcdirs = fu_split_path((File.realdirpath(s) rescue File.expand_path(s)))
base = fu_relative_components_from(srcdirs, destdirs)
s = File.join(*base)
else
srcdirs = fu_clean_components(*fu_split_path(s))
base = fu_relative_components_from(fu_split_path(Dir.pwd), destdirs)
while srcdirs.first&. == ".." and base.last&.!=("..") and !fu_starting_path?(base.last)
srcdirs.shift
base.pop
end
s = File.join(*base, *srcdirs)
end
fu_output_message "ln -s#{options} #{s} #{d}" if verbose
next if noop
remove_file d, true if force
File.symlink s, d
end
case srcs.size
when 0
when 1
link[srcs[0], target_directory && File.directory?(dest)]
else
srcs.each(&link)
end
end Как FileUtils.ln_s, но создаёт ссылки относительно dest.
# File lib/fileutils.rb, line 317
def mkdir(list, mode: nil, noop: nil, verbose: nil)
list = fu_list(list)
fu_output_message "mkdir #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}" if verbose
return if noop
list.each do |dir|
fu_mkdir dir, mode
end
end Создаёт каталоги по путям из заданного list (один путь или массив путей); возвращает list, если это массив, и [list] в противном случае.
Аргумент list или его элементы должны быть интерпретируемы как пути.
Если именованные аргументы не заданы, создаёт каталог по каждому path в list, вызывая: Dir.mkdir(path, mode); см. Dir.mkdir:
FileUtils.mkdir(%w[tmp0 tmp1]) # => ["tmp0", "tmp1"]
FileUtils.mkdir('tmp4') # => ["tmp4"]
Именованные аргументы:
-
mode: mode— также вызываетFile.chmod(mode, path); см.File.chmod. -
noop: true— не создаёт каталоги. -
verbose: true— выводит эквивалентную команду:FileUtils.mkdir(%w[tmp0 tmp1], verbose: true) FileUtils.mkdir(%w[tmp2 tmp3], mode: 0700, verbose: true)
Вывод:
mkdir tmp0 tmp1 mkdir -m 700 tmp2 tmp3
Вызывает исключение, если какой-либо путь указывает на существующий файл или каталог либо если по какой-либо причине не удаётся создать каталог.
Связанный метод: FileUtils.mkdir_p.
# File lib/fileutils.rb, line 366
def mkdir_p(list, mode: nil, noop: nil, verbose: nil)
list = fu_list(list)
fu_output_message "mkdir -p #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}" if verbose
return *list if noop
list.each do |item|
path = remove_trailing_slash(item)
stack = []
until File.directory?(path) || File.dirname(path) == path
stack.push path
path = File.dirname(path)
end
stack.reverse_each do |dir|
begin
fu_mkdir dir, mode
rescue SystemCallError
raise unless File.directory?(dir)
end
end
end
return *list
end Создаёт каталоги по путям из заданного list (один путь или массив путей), при необходимости создавая также родительские каталоги; возвращает list, если это массив, и [list] в противном случае.
Аргумент list или его элементы должны быть интерпретируемы как пути.
Если именованные аргументы не заданы, создаёт каталог по каждому path в list, а также все необходимые родительские каталоги, вызывая: Dir.mkdir(path, mode); см. Dir.mkdir:
FileUtils.mkdir_p(%w[tmp0/tmp1 tmp2/tmp3]) # => ["tmp0/tmp1", "tmp2/tmp3"]
FileUtils.mkdir_p('tmp4/tmp5') # => ["tmp4/tmp5"]
Именованные аргументы:
-
mode: mode— также вызываетFile.chmod(mode, path); см.File.chmod. -
noop: true— не создаёт каталоги. -
verbose: true— выводит эквивалентную команду:FileUtils.mkdir_p(%w[tmp0 tmp1], verbose: true) FileUtils.mkdir_p(%w[tmp2 tmp3], mode: 0700, verbose: true)
Вывод:
mkdir -p tmp0 tmp1 mkdir -p -m 700 tmp2 tmp3
Вызывает исключение, если по какой-либо причине не удаётся создать каталог.
FileUtils.mkpath и FileUtils.makedirs — псевдонимы для FileUtils.mkdir_p.
Связанный метод: FileUtils.mkdir.
# File lib/fileutils.rb, line 1158
def mv(src, dest, force: nil, noop: nil, verbose: nil, secure: nil)
fu_output_message "mv#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose
return if noop
fu_each_src_dest(src, dest) do |s, d|
destent = Entry_.new(d, nil, true)
begin
if destent.exist?
if destent.directory?
raise Errno::EEXIST, d
end
end
begin
File.rename s, d
rescue Errno::EXDEV,
Errno::EPERM # move from unencrypted to encrypted dir (ext4)
copy_entry s, d, true
if secure
remove_entry_secure s, force
else
remove_entry s, force
end
end
rescue SystemCallError
raise unless force
end
end
end Перемещает элементы.
Аргументы src (один путь или массив путей) и dest (один путь) должны быть интерпретируемы как пути.
Если src и dest находятся в разных файловых системах, сначала копирует, а затем удаляет src.
Может создать локальную уязвимость, если вызван без именованного аргумента secure: true; см. Как избежать уязвимости TOCTTOU.
Если src — путь к отдельному файлу или каталогу, а dest не существует, перемещает src в dest:
tree('src0')
# => src0
# |-- src0.txt
# `-- src1.txt
File.exist?('dest0') # => false
FileUtils.mv('src0', 'dest0')
File.exist?('src0') # => false
tree('dest0')
# => dest0
# |-- src0.txt
# `-- src1.txt
Если src — массив путей к файлам и каталогам, а dest — путь к каталогу, копирует каждый путь из массива в dest:
File.file?('src1.txt') # => true
tree('src1')
# => src1
# |-- src.dat
# `-- src.txt
Dir.empty?('dest1') # => true
FileUtils.mv(['src1.txt', 'src1'], 'dest1')
tree('dest1')
# => dest1
# |-- src1
# | |-- src.dat
# | `-- src.txt
# `-- src1.txt
Именованные аргументы:
-
force: true— если перемещение включает удалениеsrc(то есть еслиsrcиdestнаходятся в разных файловых системах), игнорирует вызванные исключенияStandardErrorи его подклассов. -
noop: true— не перемещает файлы. -
secure: true— безопасно удаляетsrc; подробности см. вFileUtils.remove_entry_secure. -
verbose: true— выводит эквивалентную команду:FileUtils.mv('src0', 'dest0', noop: true, verbose: true) FileUtils.mv(['src1.txt', 'src1'], 'dest1', noop: true, verbose: true)Вывод:
mv src0 dest0 mv src1.txt src1 dest1
# File lib/fileutils.rb, line 198 def pwd Dir.pwd end
Возвращает строку, содержащую путь к текущему каталогу:
FileUtils.pwd # => "/rdoc/fileutils"
Связанный метод: FileUtils.cd.
# File lib/fileutils.rb, line 1493 def remove_dir(path, force = false) remove_entry path, force # FIXME?? check if it is a directory end
Рекурсивно удаляет элемент каталога, заданный path, который должен быть элементом обычного файла, символической ссылки или каталога.
Аргумент path должен быть интерпретируем как путь.
Необязательный аргумент force указывает, следует ли игнорировать вызванные исключения StandardError и его подклассов.
Связанные методы: методы удаления.
# File lib/fileutils.rb, line 1450
def remove_entry(path, force = false)
Entry_.new(path).postorder_traverse do |ent|
begin
ent.remove
rescue
raise unless force
end
end
rescue
raise unless force
end Удаляет элемент, заданный path, который должен быть элементом обычного файла, символической ссылки или каталога.
Аргумент path должен быть интерпретируем как путь.
Необязательный аргумент force указывает, следует ли игнорировать вызванные исключения StandardError и его подклассов.
Связанный метод: FileUtils.remove_entry_secure.
# File lib/fileutils.rb, line 1352
def remove_entry_secure(path, force = false)
unless fu_have_symlink?
remove_entry path, force
return
end
fullpath = File.expand_path(path)
st = File.lstat(fullpath)
unless st.directory?
File.unlink fullpath
return
end
# is a directory.
parent_st = File.stat(File.dirname(fullpath))
unless parent_st.world_writable?
remove_entry path, force
return
end
unless parent_st.sticky?
raise ArgumentError, "parent directory is world writable, FileUtils#remove_entry_secure does not work; abort: #{path.inspect} (parent directory mode #{'%o' % parent_st.mode})"
end
# freeze tree root
euid = Process.euid
dot_file = fullpath + "/."
begin
File.open(dot_file) {|f|
unless fu_stat_identical_entry?(st, f.stat)
# symlink (TOC-to-TOU attack?)
File.unlink fullpath
return
end
f.chown euid, -1
f.chmod 0700
}
rescue Errno::EISDIR # JRuby in non-native mode can't open files as dirs
File.lstat(dot_file).tap {|fstat|
unless fu_stat_identical_entry?(st, fstat)
# symlink (TOC-to-TOU attack?)
File.unlink fullpath
return
end
File.chown euid, -1, dot_file
File.chmod 0700, dot_file
}
end
unless fu_stat_identical_entry?(st, File.lstat(fullpath))
# TOC-to-TOU attack?
File.unlink fullpath
return
end
# ---- tree root is frozen ----
root = Entry_.new(path)
root.preorder_traverse do |ent|
if ent.directory?
ent.chown euid, -1
ent.chmod 0700
end
end
root.postorder_traverse do |ent|
begin
ent.remove
rescue
raise unless force
end
end
rescue
raise unless force
end Безопасно удаляет элемент, заданный path, который должен быть элементом обычного файла, символической ссылки или каталога.
Аргумент path должен быть интерпретируем как путь.
Предотвращает локальную уязвимость, которая может возникнуть при определённых обстоятельствах; см. Как избежать уязвимости TOCTTOU.
Необязательный аргумент force указывает, следует ли игнорировать вызванные исключения StandardError и его подклассов.
Связанные методы: методы удаления.
# File lib/fileutils.rb, line 1474 def remove_file(path, force = false) Entry_.new(path).remove_file rescue raise unless force end
Удаляет элемент файла, заданный path, который должен быть элементом обычного файла или символической ссылки.
Аргумент path должен быть интерпретируем как путь.
Необязательный аргумент force указывает, следует ли игнорировать вызванные исключения StandardError и его подклассов.
Связанные методы: методы удаления.
# File lib/fileutils.rb, line 1217
def rm(list, force: nil, noop: nil, verbose: nil)
list = fu_list(list)
fu_output_message "rm#{force ? ' -f' : ''} #{list.join ' '}" if verbose
return if noop
list.each do |path|
remove_file path, force
end
end Удаляет элементы по путям из заданного list (один путь или массив путей); возвращает list, если это массив, и [list] в противном случае.
Аргумент list или его элементы должны быть интерпретируемы как пути.
Если именованные аргументы не заданы, удаляет файлы по путям из list:
FileUtils.touch(['src0.txt', 'src0.dat']) FileUtils.rm(['src0.dat', 'src0.txt']) # => ["src0.dat", "src0.txt"]
Именованные аргументы:
-
force: true— игнорирует вызванные исключенияStandardErrorи его подклассов. -
noop: true— не удаляет файлы; возвращаетnil. -
verbose: true— выводит эквивалентную команду:FileUtils.rm(['src0.dat', 'src0.txt'], noop: true, verbose: true)
Вывод:
rm src0.dat src0.txt
Связанные методы: методы удаления.
# File lib/fileutils.rb, line 1242 def rm_f(list, noop: nil, verbose: nil) rm list, force: true, noop: noop, verbose: verbose end
Эквивалентно:
FileUtils.rm(list, force: true, **kwargs)
Аргумент list (один путь или массив путей) должен быть интерпретируем как путь.
Список именованных аргументов см. в FileUtils.rm.
Связанные методы: методы удаления.
# File lib/fileutils.rb, line 1300
def rm_r(list, force: nil, noop: nil, verbose: nil, secure: nil)
list = fu_list(list)
fu_output_message "rm -r#{force ? 'f' : ''} #{list.join ' '}" if verbose
return if noop
list.each do |path|
if secure
remove_entry_secure path, force
else
remove_entry path, force
end
end
end Удаляет элементы по путям из заданного list (один путь или массив путей); возвращает list, если это массив, и [list] в противном случае.
Аргумент list или его элементы должны быть интерпретируемы как пути.
Может создать локальную уязвимость, если вызван без именованного аргумента secure: true; см. Как избежать уязвимости TOCTTOU.
Для каждого пути к файлу удаляет файл по этому пути:
FileUtils.touch(['src0.txt', 'src0.dat'])
FileUtils.rm_r(['src0.dat', 'src0.txt'])
File.exist?('src0.txt') # => false
File.exist?('src0.dat') # => false
Для каждого пути к каталогу рекурсивно удаляет файлы и каталоги:
tree('src1')
# => src1
# |-- dir0
# | |-- src0.txt
# | `-- src1.txt
# `-- dir1
# |-- src2.txt
# `-- src3.txt
FileUtils.rm_r('src1')
File.exist?('src1') # => false
Именованные аргументы:
-
force: true— игнорирует вызванные исключенияStandardErrorи его подклассов. -
noop: true— не удаляет элементы; возвращаетnil. -
secure: true— безопасно удаляетsrc; подробности см. вFileUtils.remove_entry_secure. -
verbose: true— выводит эквивалентную команду:FileUtils.rm_r(['src0.dat', 'src0.txt'], noop: true, verbose: true) FileUtils.rm_r('src1', noop: true, verbose: true)Вывод:
rm -r src0.dat src0.txt rm -r src1
Связанные методы: методы удаления.
# File lib/fileutils.rb, line 1329 def rm_rf(list, noop: nil, verbose: nil, secure: nil) rm_r list, force: true, noop: noop, verbose: verbose, secure: secure end
Эквивалентно:
FileUtils.rm_r(list, force: true, **kwargs)
Аргумент list или его элементы должны быть интерпретируемы как пути.
Может создать локальную уязвимость, если вызван без именованного аргумента secure: true; см. Как избежать уязвимости TOCTTOU.
Список именованных аргументов см. в FileUtils.rm_r.
Связанные методы: методы удаления.
# File lib/fileutils.rb, line 443
def rmdir(list, parents: nil, noop: nil, verbose: nil)
list = fu_list(list)
fu_output_message "rmdir #{parents ? '-p ' : ''}#{list.join ' '}" if verbose
return if noop
list.each do |dir|
Dir.rmdir(dir = remove_trailing_slash(dir))
if parents
begin
until (parent = File.dirname(dir)) == '.' or parent == dir
dir = parent
Dir.rmdir(dir)
end
rescue Errno::ENOTEMPTY, Errno::EEXIST, Errno::ENOENT
end
end
end
end Удаляет каталоги по путям из заданного list (один путь или массив путей); возвращает list, если это массив, и [list] в противном случае.
Аргумент list или его элементы должны быть интерпретируемы как пути.
Если именованные аргументы не заданы, удаляет каталог по каждому path в list, вызывая: Dir.rmdir(path); см. Dir.rmdir:
FileUtils.rmdir(%w[tmp0/tmp1 tmp2/tmp3]) # => ["tmp0/tmp1", "tmp2/tmp3"]
FileUtils.rmdir('tmp4/tmp5') # => ["tmp4/tmp5"]
Именованные аргументы:
-
parents: true— удаляет последовательно родительские каталоги, если они пусты. -
noop: true— не удаляет каталоги. -
verbose: true— выводит эквивалентную команду:FileUtils.rmdir(%w[tmp0/tmp1 tmp2/tmp3], parents: true, verbose: true) FileUtils.rmdir('tmp4/tmp5', parents: true, verbose: true)Вывод:
rmdir -p tmp0/tmp1 tmp2/tmp3 rmdir -p tmp4/tmp5
Вызывает исключение, если каталог не существует или если по какой-либо причине его не удаётся удалить.
Связанные методы: методы удаления.
# File lib/fileutils.rb, line 2007
def touch(list, noop: nil, verbose: nil, mtime: nil, nocreate: nil)
list = fu_list(list)
t = mtime
if verbose
fu_output_message "touch #{nocreate ? '-c ' : ''}#{t ? t.strftime('-t %Y%m%d%H%M.%S ') : ''}#{list.join ' '}"
end
return if noop
list.each do |path|
created = nocreate
begin
File.utime(t, t, path)
rescue Errno::ENOENT
raise if created
File.open(path, 'a') {
;
}
created = true
retry if t
end
end
end Обновляет время изменения (mtime) и время доступа (atime) элементов, заданных путями в list (один путь или массив путей); возвращает list, если это массив, и [list] в противном случае.
По умолчанию создаёт пустой файл для каждого пути, соответствующего несуществующему элементу; чтобы вместо этого вызвать исключение, используйте именованный аргумент nocreate.
Аргумент list или его элементы должны быть интерпретируемы как пути.
Примеры:
# Single path.
f = File.new('src0.txt') # Existing file.
f.atime # => 2022-06-10 11:11:21.200277 -0700
f.mtime # => 2022-06-10 11:11:21.200277 -0700
FileUtils.touch('src0.txt')
f = File.new('src0.txt')
f.atime # => 2022-06-11 08:28:09.8185343 -0700
f.mtime # => 2022-06-11 08:28:09.8185343 -0700
# Array of paths.
FileUtils.touch(['src0.txt', 'src0.dat'])
Именованные аргументы:
-
mtime: time— задаёт для элемента указанное время mtime вместо текущего времени. -
nocreate: true— вызывает исключение, если элемент не существует. -
noop: true— не изменяет время элементов; возвращаетnil. -
verbose: true— выводит эквивалентную команду:FileUtils.touch('src0.txt', noop: true, verbose: true) FileUtils.touch(['src0.txt', 'src0.dat'], noop: true, verbose: true) FileUtils.touch(path, noop: true, verbose: true)Вывод:
touch src0.txt touch src0.txt src0.dat touch src0.txt
Связанный метод: FileUtils.uptodate?.
# File lib/fileutils.rb, line 265
def uptodate?(new, old_list)
return false unless File.exist?(new)
new_time = File.mtime(new)
old_list.each do |old|
if File.exist?(old)
return false unless new_time > File.mtime(old)
end
end
true
end Возвращает true, если файл по пути new новее всех файлов по путям из массива old_list; в противном случае возвращает false.
Аргумент new и элементы old_list должны быть интерпретируемы как пути:
FileUtils.uptodate?('Rakefile', ['Gemfile', 'README.md']) # => true
FileUtils.uptodate?('Gemfile', ['Rakefile', 'README.md']) # => false
Несуществующий файл считается бесконечно старым.
Связанный метод: FileUtils.touch.
Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.