Spec-Zone.ru › Ruby 2.7

Модуль FileUtils

Включенные модули:
FileUtils::StreamUtils_

fileutils.rb

Авторское право © 2000-2007 Minero Aoki

Данная программа является свободной программной. Вы можете распространять/изменять данную программу на тех же условиях, что и руби.

Модуль FileUtils

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

Module Функции

require 'fileutils'

FileUtils.cd(dir, **options)
FileUtils.cd(dir, **options) {|dir| block }
FileUtils.pwd()
FileUtils.mkdir(dir, **options)
FileUtils.mkdir(list, **options)
FileUtils.mkdir_p(dir, **options)
FileUtils.mkdir_p(list, **options)
FileUtils.rmdir(dir, **options)
FileUtils.rmdir(list, **options)
FileUtils.ln(target, link, **options)
FileUtils.ln(targets, dir, **options)
FileUtils.ln_s(target, link, **options)
FileUtils.ln_s(targets, dir, **options)
FileUtils.ln_sf(target, link, **options)
FileUtils.cp(src, dest, **options)
FileUtils.cp(list, dir, **options)
FileUtils.cp_r(src, dest, **options)
FileUtils.cp_r(list, dir, **options)
FileUtils.mv(src, dest, **options)
FileUtils.mv(list, dir, **options)
FileUtils.rm(list, **options)
FileUtils.rm_r(list, **options)
FileUtils.rm_rf(list, **options)
FileUtils.install(src, dest, **options)
FileUtils.chmod(mode, list, **options)
FileUtils.chmod_R(mode, list, **options)
FileUtils.chown(user, group, list, **options)
FileUtils.chown_R(user, group, list, **options)
FileUtils.touch(list, **options)

Возможные options:

:force

вынужденная операция (перезапись файлов, если они существуют, удаление каталогов, если они не пустые и т.д.);

:verbose

вывод команды, которая будет выполнена, в формате bash, перед ее выполнением;

:preserve

сохранение группы, пользователя и времени изменения объекта при копировании;

:noop

без изменений (можно использовать в сочетании с :verbose, который выведет команду для выполнения)

Каждый метод документирует параметры, которые он поддерживает. См. также методы ::commands, ::options и ::options_of для получения информации о командах и их параметрах.

Все методы, которые имеют понятие «исходного» файла или каталога, могут принимать как один файл, так и список файлов в качестве аргумента. Примеры использования см. в документации к методам.

Есть некоторые методы «нижележащего уровня», которые не принимают именованные аргументы:

FileUtils.copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false)
FileUtils.copy_file(src, dest, preserve = false, dereference = true)
FileUtils.copy_stream(srcstream, deststream)
FileUtils.remove_entry(path, force = false)
FileUtils.remove_entry_secure(path, force = false)
FileUtils.remove_file(path, force = false)
FileUtils.compare_file(path_a, path_b)
FileUtils.compare_stream(stream_a, stream_b)
FileUtils.uptodate?(file, cmp_list)

Модуль FileUtils::Verbose

Этот модуль содержит все методы модуля FileUtils, но выводит сообщения перед выполнением действий. Это эквивалентно передаче флага :verbose методам в модуле FileUtils.

Модуль FileUtils::NoWrite

Этот модуль содержит все методы модуля FileUtils, но никогда не изменяет файлы/каталоги. Это эквивалентно передаче флага :noop методам в модуле FileUtils.

Модуль FileUtils::DryRun

Этот модуль содержит все методы модуля FileUtils, но никогда не изменяет файлы/каталоги. Это эквивалентно передаче флагов :noop и :verbose методам в модуле FileUtils.

Константы

VERSION

Методы открытого класса

cd(dir, verbose: nil) { |dir| ... } Показать исходный код
# File lib/fileutils.rb, line 137
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.

Если этот метод вызван с блоком, он возвращается к предыдущей рабочей директории после завершения выполнения блока.

FileUtils.cd('/')  # change directory

FileUtils.cd('/', verbose: true)   # change directory and report it

FileUtils.cd('/') do  # change directory
  # ...               # do something
end                   # return to original directory
Также алиас: chdir
chdir(dir, verbose: nil)
Псевдоним для: cd
chmod(mode, list, noop: nil, verbose: nil) Показать исходный код
# File lib/fileutils.rb, line 1012
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.

Можно использовать символьную и абсолютную нотацию.

Абсолютная нотация:

FileUtils.chmod 0755, 'somecommand'
FileUtils.chmod 0644, %w(my.rb your.rb his.rb her.rb)
FileUtils.chmod 0755, '/usr/bin/ruby', verbose: true

Символьная нотация:

FileUtils.chmod "u=wrx,go=rx", 'somecommand'
FileUtils.chmod "u=wr,go=rr", %w(my.rb your.rb his.rb her.rb)
FileUtils.chmod "u=wrx,go=rx", '/usr/bin/ruby', verbose: true
“a”

— маска для пользователя, группы и других.

“u”

— маска для пользователя.

“g”

— маска для группы.

“o”

— маска для других.

“w”

— разрешение на запись.

“r”

— разрешение на чтение.

“x”

— разрешение на выполнение.

“X”

— разрешение на выполнение только для каталогов, должно использоваться в сочетании с “+”

“s”

— идентификатор пользователя и группы.

“t”

— битовая метка «всё ещё в каталоге» (sticky bit).

“+”

— добавляет к классу, заданному в режиме.

“-”

— удаляет из класса, заданного в режиме.

“=”

— точно задаёт класс в соответствии с режимом.

chmod_R(mode, list, noop: nil, verbose: nil, force: nil) Показать исходный код
# File lib/fileutils.rb, line 1029
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

Изменяет биты разрешений на указанные файлы (в list) на битовую маску, представленную значением mode рекурсивно.

FileUtils.chmod_R 0700, "/tmp/app.#{$$}"
FileUtils.chmod_R "u=wrx", "/tmp/app.#{$$}"
chown(user, group, list, noop: nil, verbose: nil) Показать исходный код
# File lib/fileutils.rb, line 1057
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. user и group могут быть ID (целое число/строка) или именем (String). Если user или group имеют значение nil, этот метод не изменяет атрибут.

FileUtils.chown 'root', 'staff', '/usr/local/bin/ruby'
FileUtils.chown nil, 'bin', Dir.glob('/usr/bin/*'), verbose: true
chown_R(user, group, list, noop: nil, verbose: nil, force: nil) Показать исходный код
# File lib/fileutils.rb, line 1081
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

Изменяет владельца и группу на указанные файлы (в list) на пользователя user и группу group рекурсивно. user и group могут быть ID (целое число/строка) или именем (String). Если user или group имеют значение nil, этот метод не изменяет атрибут.

FileUtils.chown_R 'www', 'www', '/var/www/htdocs'
FileUtils.chown_R 'cvs', 'cvs', '/var/cvs', verbose: true
cmp(a, b)
Псевдоним для: compare_file
collect_method(opt) Показать исходный код
# File lib/fileutils.rb, line 1680
def self.collect_method(opt)
  OPT_TABLE.keys.select {|m| OPT_TABLE[m].include?(opt) }
end

Возвращает Array имён методов, имеющих опцию opt.

p FileUtils.collect_method(:preserve) #=> ["cp", "cp_r", "copy", "install"]
commands() Показать исходный код
# File lib/fileutils.rb, line 1641
def self.commands
  OPT_TABLE.keys
end

Возвращает Array имён методов высокого уровня, которые принимают любые ключевые аргументы.

p FileUtils.commands  #=> ["chmod", "cp", "cp_r", "install", ...]
compare_file(a, b) Показать исходный код
# File lib/fileutils.rb, line 816
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 идентичны.

FileUtils.compare_file('somefile', 'somefile')       #=> true
FileUtils.compare_file('/dev/null', '/dev/urandom')  #=> false
Также алиас: identical?, cmp
compare_stream(a, b) Показать исходный код
# File lib/fileutils.rb, line 834
def compare_stream(a, b)
  bsize = fu_stream_blksize(a, b)

  if RUBY_VERSION > "2.4"
    sa = String.new(capacity: bsize)
    sb = String.new(capacity: bsize)
  else
    sa = String.new
    sb = String.new
  end

  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 идентичны.

copy(src, dest, preserve: nil, noop: nil, verbose: nil)
Псевдоним для: cp
copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false) Показать исходный код
# File lib/fileutils.rb, line 489
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 — это каталог, этот метод копирует его содержимое рекурсивно. Этот метод сохраняет типы файлов, например, символические ссылки, каталоги… (FIFO, файлы устройств и т. д. пока не поддерживаются)

И src и dest должны быть именами путей. src должен существовать, dest не должен существовать.

Если preserve имеет значение true, этот метод сохраняет владельца, группу и время изменения. Разрешения копируются независимо от preserve.

Если dereference_root имеет значение true, этот метод делает рекурсивный спуск по корню.

Если remove_destination имеет значение true, этот метод удаляет каждый файл назначения перед копированием.

copy_file(src, dest, preserve = false, dereference = true) Показать исходный код
# File lib/fileutils.rb, line 509
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 должны быть именами путей.

copy_stream(src, dest) Показать исходный код
# File lib/fileutils.rb, line 521
def copy_stream(src, dest)
  IO.copy_stream(src, dest)
end

Копирует поток src в dest. src должен отвечать на read(n), а dest — на write(str).

cp(src, dest, preserve: nil, noop: nil, verbose: nil) Показать исходный код
# File lib/fileutils.rb, line 426
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. Если dest — это каталог, копирует src в dest/src.

Если src — это список файлов, то dest должен быть каталогом.

FileUtils.cp 'eval.c', 'eval.c.org'
FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6'
FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6', verbose: true
FileUtils.cp 'symlink', 'dest'   # copy content, "dest" is not a symlink
Также алиас: copy
cp_lr(src, dest, noop: nil, verbose: nil, dereference_root: true, remove_destination: false) Показать исходный код
# File lib/fileutils.rb, line 339
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 — это каталог, он создаёт ссылки на src в dest/src.

src может быть списком файлов.

Если dereference_root имеет значение true, этот метод делает рекурсивный спуск по корню.

Если remove_destination имеет значение true, этот метод удаляет каждый файл назначения перед копированием.

FileUtils.rm_r site_ruby + '/mylib', force: true
FileUtils.cp_lr 'lib/', site_ruby + '/mylib'

# Examples of linking several files to target directory.
FileUtils.cp_lr %w(mail.rb field.rb debug/), site_ruby + '/tmail'
FileUtils.cp_lr Dir.glob('*.rb'), '/home/aamine/lib/ruby', noop: true, verbose: true

# If you want to link all contents of a directory instead of the
# directory itself, c.f. src/x -> dest/x, src/y -> dest/y,
# use the following code.
FileUtils.cp_lr 'src/.', 'dest'  # cp_lr('src', 'dest') makes dest/src, but this doesn't.
cp_r(src, dest, preserve: nil, noop: nil, verbose: nil, dereference_root: true, remove_destination: nil) Показать исходный код
# File lib/fileutils.rb, line 463
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. Если src является каталогом, этот метод копирует все его содержимое рекурсивно. Если dest является каталогом, копирует src в dest/src.

src может быть списком файлов.

Если dereference_root имеет значение true, этот метод обрабатывает корень дерева.

Если remove_destination имеет значение true, этот метод удаляет каждый целевой файл перед копированием.

# Installing Ruby library "mylib" under the site_ruby
FileUtils.rm_r site_ruby + '/mylib', force: true
FileUtils.cp_r 'lib/', site_ruby + '/mylib'

# Examples of copying several files to target directory.
FileUtils.cp_r %w(mail.rb field.rb debug/), site_ruby + '/tmail'
FileUtils.cp_r Dir.glob('*.rb'), '/home/foo/lib/ruby', noop: true, verbose: true

# If you want to copy all contents of a directory instead of the
# directory itself, c.f. src/x -> dest/x, src/y -> dest/y,
# use following code.
FileUtils.cp_r 'src/.', 'dest'     # cp_r('src', 'dest') makes dest/src,
                                   # but this doesn't.
getwd()
Псевдоним для: pwd
have_option?(mid, opt) Показать исходный код
# File lib/fileutils.rb, line 1661
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.

p FileUtils.have_option?(:cp, :noop)     #=> true
p FileUtils.have_option?(:rm, :force)    #=> true
p FileUtils.have_option?(:rm, :preserve) #=> false
identical?(a, b)
Псевдоним для: compare_file
install(src, dest, mode: nil, owner: nil, group: nil, preserve: nil, noop: nil, verbose: nil) Показать исходный код
# File lib/fileutils.rb, line 862
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
      copy_file s, d
      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

Если src не совпадает с dest, копирует его и изменяет режим доступа на mode. Если dest является каталогом, то результатом является dest/src. Этот метод удаляет целевой объект перед копированием.

FileUtils.install 'ruby', '/usr/local/bin/ruby', mode: 0755, verbose: true
FileUtils.install 'lib.rb', '/usr/local/lib/ruby/site_ruby', verbose: true
link(src, dest, force: nil, noop: nil, verbose: nil)
Псевдоним для: ln
link_entry(src, dest, dereference_root = false, remove_destination = false) Показать исходный код
# File lib/fileutils.rb, line 406
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

Создаёт жёсткую ссылку на системный элемент src в dest. Если src является каталогом, этот метод создаёт жёсткие ссылки на его содержимое рекурсивно.

Оба src и dest должны быть именами путей. src должен существовать, а dest — нет.

Если dereference_root имеет значение true, этот метод обрабатывает корень дерева.

Если remove_destination имеет значение true, этот метод удаляет каждый целевой файл перед копированием.

ln(target, link, force: nil, noop: nil, verbose: nil) Показать исходный код
ln(target, dir, force: nil, noop: nil, verbose: nil)
ln(targets, dir, force: nil, noop: nil, verbose: nil)
# File lib/fileutils.rb, line 303
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

В первом случае создаёт жёсткую ссылку link, которая указывает на target. Если link уже существует, возникает исключение Errno::EEXIST. Но если опция force установлена, переписывает link.

FileUtils.ln 'gcc', 'cc', verbose: true
FileUtils.ln '/usr/bin/emacs21', '/usr/bin/emacs'

Во втором случае создаёт ссылку dir/target указывающую на target. В третьем случае создаёт несколько жёстких ссылок в каталоге dir, указывающих на каждый элемент в targets. Если dir не является каталогом, возникает исключение Errno::ENOTDIR.

FileUtils.cd '/sbin'
FileUtils.ln %w(cp mv mkdir), '/bin'   # Now /sbin/cp and /bin/cp are linked.
Также используется как: link
ln_s(target, link, force: nil, noop: nil, verbose: nil) Показать исходный код
ln_s(target, dir, force: nil, noop: nil, verbose: nil)
ln_s(targets, dir, force: nil, noop: nil, verbose: nil)
# File lib/fileutils.rb, line 369
def ln_s(src, dest, force: nil, noop: nil, verbose: nil)
  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

В первом случае создаёт символическую ссылку link, которая указывает на target. Если link уже существует, возникает исключение Errno::EEXIST. Но если опция force установлена, переписывает link.

FileUtils.ln_s '/usr/bin/ruby', '/usr/local/bin/ruby'
FileUtils.ln_s 'verylongsourcefilename.c', 'c', force: true

Во втором случае создаёт ссылку dir/target указывающую на target. В третьем случае создаёт несколько символических ссылок в каталоге dir, указывающих на каждый элемент в targets. Если dir не является каталогом, возникает исключение Errno::ENOTDIR.

FileUtils.ln_s Dir.glob('/bin/*.rb'), '/home/foo/bin'
Также используется как: symlink
ln_sf(*args) Показать исходный код
# File lib/fileutils.rb, line 390
def ln_sf(src, dest, noop: nil, verbose: nil)
  ln_s src, dest, force: true, noop: noop, verbose: verbose
end

То же, что

FileUtils.ln_s(*args, force: true)
makedirs(list, mode: nil, noop: nil, verbose: nil)
Псевдоним для: mkdir_p
mkdir(list, mode: nil, noop: nil, verbose: nil) Показать исходный код
# File lib/fileutils.rb, line 180
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

Создаёт один или несколько каталогов.

FileUtils.mkdir 'test'
FileUtils.mkdir %w(tmp data)
FileUtils.mkdir 'notexist', noop: true  # Does not really create.
FileUtils.mkdir 'tmp', mode: 0700
mkdir_p(list, mode: nil, noop: nil, verbose: nil) Показать исходный код
# File lib/fileutils.rb, line 206
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.map {|path| remove_trailing_slash(path)}.each do |path|
    # optimize for the most common case
    begin
      fu_mkdir path, mode
      next
    rescue SystemCallError
      next if File.directory?(path)
    end

    stack = []
    until path == stack.last   # dirname("/")=="/", dirname("C:/")=="C:/"
      stack.push path
      path = File.dirname(path)
    end
    stack.pop                 # root directory should exist
    stack.reverse_each do |dir|
      begin
        fu_mkdir dir, mode
      rescue SystemCallError
        raise unless File.directory?(dir)
      end
    end
  end

  return *list
end

Создаёт каталог и все его родительские каталоги. Например,

FileUtils.mkdir_p '/usr/local/lib/ruby'

приводит к созданию следующих каталогов, если они не существуют.

  • /usr

  • /usr/local

  • /usr/local/lib

  • /usr/local/lib/ruby

Вы можете передать несколько каталогов одновременно в списке.

Также используется как: mkpath, makedirs
mkpath(list, mode: nil, noop: nil, verbose: nil)
Псевдоним для: mkdir_p
move(src, dest, force: nil, noop: nil, verbose: nil, secure: nil)
Псевдоним для: mv
mv(src, dest, force: nil, noop: nil, verbose: nil, secure: nil) Показать исходный код
# File lib/fileutils.rb, line 536
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. Если file и dest находятся на разных разделах диска, файл копируется, а исходный файл удаляется.

FileUtils.mv 'badname.rb', 'goodname.rb'
FileUtils.mv 'stuff.rb', '/notexist/lib/ruby', force: true  # no error

FileUtils.mv %w(junk.txt dust.txt), '/home/foo/.trash/'
FileUtils.mv Dir.glob('test*.rb'), 'test', noop: true, verbose: true
Также используется как: move
options() Показать исходный код
# File lib/fileutils.rb, line 1650
def self.options
  OPT_TABLE.values.flatten.uniq.map {|sym| sym.to_s }
end

Возвращает Array список имён опций.

p FileUtils.options  #=> ["noop", "force", "verbose", "preserve", "mode"]
options_of(mid) Показать исходный код
# File lib/fileutils.rb, line 1671
def self.options_of(mid)
  OPT_TABLE[mid.to_s].map {|sym| sym.to_s }
end

Возвращает Array список имён опций метода mid.

p FileUtils.options_of(:rm)  #=> ["noop", "verbose", "force"]
pwd() Показать исходный код
# File lib/fileutils.rb, line 115
def pwd
  Dir.pwd
end

Возвращает имя текущего каталога.

Также используется как: getwd
END_OF_DOCUMENT_MARKER
remove(list, force: nil, noop: nil, verbose: nil)
Псевдоним для: rm
remove_dir(path, force = false) Показать исходный код
# File lib/fileutils.rb, line 805
def remove_dir(path, force = false)
  remove_entry path, force   # FIXME?? check if it is a directory
end

Удаляет директорию dir и её содержимое рекурсивно. Этот метод игнорирует StandardError, если force равно true.

remove_entry(path, force = false) Показать исходный код
# File lib/fileutils.rb, line 777
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 может быть обычным файлом, директорией или чем-то другим. Если path является директорией, удаляет её рекурсивно.

См. также remove_entry_secure.

remove_entry_secure(path, force = false) Показать исходный код
# File lib/fileutils.rb, line 684
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 должен быть обычным файлом, директорией или чем-то другим. Если path является директорией, удаляет её рекурсивно. Этот метод необходим для предотвращения локальной проблемы безопасности TOCTTOU (time-of-check-to-time-of-use) метода rm_r. rm_r создаёт уязвимость в безопасности, когда:

  • Родительская директория имеет права записи для всех пользователей (включая /tmp).

  • Удаляемое дерево директорий включает директорию с правами записи для всех пользователей.

  • В системе присутствуют символические ссылки.

Чтобы избежать этой проблемы безопасности, этот метод применяет специальную предобработку. Если path является директорией, этот метод использует chown(2) и chmod(2) для всех удаляемых директорий. Это требует, чтобы текущий процесс был владельцем удаляемого дерева директорий или имел права суперпользователя (root).

ВНИМАНИЕ: Вы должны убедиться, что ВСЕ родительские директории не могут быть изменены другими неуверенными пользователями. Например, родительские директории не должны принадлежать неуверенным пользователям и не должны иметь права записи для всех пользователей, за исключением случаев, когда установлен бит "sticky".

ВНИМАНИЕ: Только владелец удаляемого дерева директорий или суперпользователь Unix (root) должны вызывать этот метод. В противном случае метод не сработает.

Для получения подробностей об этой проблеме безопасности см. случай Perl:

  • cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0448

  • cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452

Для fileutils.rb эта уязвимость была сообщена в [ruby-dev:26100].

remove_file(path, force = false) Показать исходный код
# File lib/fileutils.rb, line 794
def remove_file(path, force = false)
  Entry_.new(path).remove_file
rescue
  raise unless force
end

Удаляет файл path. Этот метод игнорирует StandardError, если force равно true.

rm(list, force: nil, noop: nil, verbose: nil) Показать исходный код
# File lib/fileutils.rb, line 576
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 файлы. Этот метод не может удалять директории. Все StandardErrors игнорируются, когда установлен параметр :force.

FileUtils.rm %w( junk.txt dust.txt )
FileUtils.rm Dir.glob('*.so')
FileUtils.rm 'NotExistFile', force: true   # never raises exception
Также псевдоним для: remove
rm_f(list, noop: nil, verbose: nil) Показать исходный код
# File lib/fileutils.rb, line 595
def rm_f(list, noop: nil, verbose: nil)
  rm list, force: true, noop: noop, verbose: verbose
end

Эквивалентно

FileUtils.rm(list, force: true)
Также псевдоним для: safe_unlink
rm_r(list, force: nil, noop: nil, verbose: nil, secure: nil) Показать исходный код
# File lib/fileutils.rb, line 622
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[0] list[1]… Если list[n] является директорией, удаляет её и всё содержимое рекурсивно. Этот метод игнорирует StandardError, когда установлен параметр :force.

FileUtils.rm_r Dir.glob('/tmp/*')
FileUtils.rm_r 'some_dir', force: true

ВНИМАНИЕ: Этот метод может привести к локальной уязвимости, если одна из родительских директорий или удаляемое дерево директорий имеют права записи для всех пользователей (включая /tmp, чьи права 1777), и текущий процесс обладает сильными привилегиями, такими как права суперпользователя (root), а в системе есть символические ссылки. Для безопасного удаления, внимательно изучите документацию remove_entry_secure и установите параметр :secure в значение true. По умолчанию secure: false.

ПРИМЕЧАНИЕ: Этот метод вызывает remove_entry_secure, если установлен параметр :secure. См. также remove_entry_secure.

rm_rf(list, noop: nil, verbose: nil, secure: nil) Показать исходный код
# File lib/fileutils.rb, line 644
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)

ВНИМАНИЕ: Этот метод может привести к локальной уязвимости. Прочитайте документацию rm_r прежде чем использовать.

Также псевдоним для: rmtree
rmdir(list, parents: nil, noop: nil, verbose: nil) Показать исходный код
# File lib/fileutils.rb, line 263
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

Удаляет одну или несколько директорий.

FileUtils.rmdir 'somedir'
FileUtils.rmdir %w(somedir anydir otherdir)
# Does not really remove directory; outputs message.
FileUtils.rmdir 'somedir', verbose: true, noop: true
rmtree(list, noop: nil, verbose: nil, secure: nil)
Псевдоним для: rm_rf
safe_unlink(list, noop: nil, verbose: nil)
Псевдоним для: rm_f
symlink(src, dest, force: nil, noop: nil, verbose: nil)
Псевдоним для: ln_s
touch(list, noop: nil, verbose: nil, mtime: nil, nocreate: nil) Показать исходный код
# File lib/fileutils.rb, line 1137
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. Файлы создаются, если они не существуют.

FileUtils.touch 'timestamp'
FileUtils.touch Dir.glob('*.c');  system 'make'
uptodate?(new, old_list) Показать исходный код
# File lib/fileutils.rb, line 155
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. Несуществующие файлы считаются старее любого файла.

FileUtils.uptodate?('hello.o', %w(hello.c hello.h)) or \
    system 'make hello.o'

Методы приватного экземпляра

cd(dir, verbose: nil) { |dir| ... } Показать исходный код
# File lib/fileutils.rb, line 137
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.

Если этот метод вызывается с блоком, он возвращается к предыдущей рабочей директории после завершения выполнения блока.

FileUtils.cd('/')  # change directory

FileUtils.cd('/', verbose: true)   # change directory and report it

FileUtils.cd('/') do  # change directory
  # ...               # do something
end                   # return to original directory
Также алиас: chdir
chdir(dir, verbose: nil)
Псевдоним для: cd
chmod(mode, list, noop: nil, verbose: nil) Показать исходный код
# File lib/fileutils.rb, line 1012
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.

Можно использовать символический и абсолютный режимы.

Абсолютный режим

FileUtils.chmod 0755, 'somecommand'
FileUtils.chmod 0644, %w(my.rb your.rb his.rb her.rb)
FileUtils.chmod 0755, '/usr/bin/ruby', verbose: true

Символический режим

FileUtils.chmod "u=wrx,go=rx", 'somecommand'
FileUtils.chmod "u=wr,go=rr", %w(my.rb your.rb his.rb her.rb)
FileUtils.chmod "u=wrx,go=rx", '/usr/bin/ruby', verbose: true
“a”

— маска пользователя, группы и других.

“u”

— маска пользователя.

“g”

— маска группы.

“o”

— маска других.

“w”

— разрешение на запись.

“r”

— разрешение на чтение.

“x”

— разрешение на выполнение.

“X”

— разрешение на выполнение только для каталогов, должно использоваться совместно с “+”

“s”

— uid, gid.

“t”

— битовая отметка.

“+”

— добавляется к классу, учитывая указанный режим.

“-”

Удаляется из указанного класса, учитывая указанный режим.

“=”

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

chmod_R(mode, list, noop: nil, verbose: nil, force: nil) Показать исходный код
# File lib/fileutils.rb, line 1029
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

Изменяет биты разрешений указанных файлов (в list) на битовую схему, представленную mode.

FileUtils.chmod_R 0700, "/tmp/app.#{$$}"
FileUtils.chmod_R "u=wrx", "/tmp/app.#{$$}"
chown(user, group, list, noop: nil, verbose: nil) Показать исходный код
# File lib/fileutils.rb, line 1057
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. user и group могут быть идентификатором (целое число/строка) или именем (String). Если user или group равно null, этот метод не изменяет атрибут.

FileUtils.chown 'root', 'staff', '/usr/local/bin/ruby'
FileUtils.chown nil, 'bin', Dir.glob('/usr/bin/*'), verbose: true
chown_R(user, group, list, noop: nil, verbose: nil, force: nil) Показать исходный код
# File lib/fileutils.rb, line 1081
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

Рекурсивно изменяет владельца и группу указанных файлов (в list) на пользователя user и группу group. user и group могут быть идентификатором (целое число/строка) или именем (String). Если user или group равно null, этот метод не изменяет атрибут.

FileUtils.chown_R 'www', 'www', '/var/www/htdocs'
FileUtils.chown_R 'cvs', 'cvs', '/var/cvs', verbose: true
cmp(a, b)
Псевдоним для: compare_file
compare_file(a, b) Показать исходный код
# File lib/fileutils.rb, line 816
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 идентичны.

FileUtils.compare_file('somefile', 'somefile')       #=> true
FileUtils.compare_file('/dev/null', '/dev/urandom')  #=> false
Также алиас: identical?, cmp
compare_stream(a, b) Показать исходный код
# File lib/fileutils.rb, line 834
def compare_stream(a, b)
  bsize = fu_stream_blksize(a, b)

  if RUBY_VERSION > "2.4"
    sa = String.new(capacity: bsize)
    sb = String.new(capacity: bsize)
  else
    sa = String.new
    sb = String.new
  end

  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 идентичны.

copy(src, dest, preserve: nil, noop: nil, verbose: nil)
Псевдоним для: cp
copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false) Показать исходный код
# File lib/fileutils.rb, line 489
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 — это каталог, этот метод рекурсивно копирует его содержимое. Этот метод сохраняет типы файлов, например, симлинки, каталоги… (FIFO, файлы устройств и т. д. пока не поддерживаются)

Оба src и dest должны быть именами путей. src должен существовать, dest не должен существовать.

Если preserve true, этот метод сохраняет владельца, группу и время изменения. Разрешения копируются независимо от preserve.

Если dereference_root true, этот метод де-ссылает корень дерева.

Если remove_destination true, этот метод удаляет каждый целевой файл перед копированием.

copy_file(src, dest, preserve = false, dereference = true) Показать исходный код
# File lib/fileutils.rb, line 509
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 должны быть именами путей.

copy_stream(src, dest) Показать исходный код
# File lib/fileutils.rb, line 521
def copy_stream(src, dest)
  IO.copy_stream(src, dest)
end

Копирует поток src в dest. src должен отвечать на read(n), а dest — на write(str).

cp(src, dest, preserve: nil, noop: nil, verbose: nil) Показать исходный код
# File lib/fileutils.rb, line 426
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. Если dest является каталогом, копирует src в dest/src.

Если src — список файлов, то dest должен быть каталогом.

FileUtils.cp 'eval.c', 'eval.c.org'
FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6'
FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6', verbose: true
FileUtils.cp 'symlink', 'dest'   # copy content, "dest" is not a symlink
Также алиас: copy
cp_lr(src, dest, noop: nil, verbose: nil, dereference_root: true, remove_destination: false) Показать исходный код
# File lib/fileutils.rb, line 339
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 — каталог, создаёт ссылки src на dest/src.

src может быть списком файлов.

Если dereference_root true, этот метод де-ссылает корень дерева.

Если remove_destination true, этот метод удаляет каждый целевой файл перед копированием.

FileUtils.rm_r site_ruby + '/mylib', force: true
FileUtils.cp_lr 'lib/', site_ruby + '/mylib'

# Examples of linking several files to target directory.
FileUtils.cp_lr %w(mail.rb field.rb debug/), site_ruby + '/tmail'
FileUtils.cp_lr Dir.glob('*.rb'), '/home/aamine/lib/ruby', noop: true, verbose: true

# If you want to link all contents of a directory instead of the
# directory itself, c.f. src/x -> dest/x, src/y -> dest/y,
# use the following code.
FileUtils.cp_lr 'src/.', 'dest'  # cp_lr('src', 'dest') makes dest/src, but this doesn't.
cp_r(src, dest, preserve: nil, noop: nil, verbose: nil, dereference_root: true, remove_destination: nil) Показать исходный код
# File lib/fileutils.rb, line 463
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. Если src — каталог, этот метод рекурсивно копирует всё его содержимое. Если dest — каталог, копирует src в dest/src.

src может быть списком файлов.

Если dereference_root true, этот метод де-ссылает корень дерева.

Если remove_destination true, этот метод удаляет каждый целевой файл перед копированием.

# Installing Ruby library "mylib" under the site_ruby
FileUtils.rm_r site_ruby + '/mylib', force: true
FileUtils.cp_r 'lib/', site_ruby + '/mylib'

# Examples of copying several files to target directory.
FileUtils.cp_r %w(mail.rb field.rb debug/), site_ruby + '/tmail'
FileUtils.cp_r Dir.glob('*.rb'), '/home/foo/lib/ruby', noop: true, verbose: true

# If you want to copy all contents of a directory instead of the
# directory itself, c.f. src/x -> dest/x, src/y -> dest/y,
# use following code.
FileUtils.cp_r 'src/.', 'dest'     # cp_r('src', 'dest') makes dest/src,
                                   # but this doesn't.
getwd()
Псевдоним для: pwd
identical?(a, b)
Псевдоним для: compare_file
install(src, dest, mode: nil, owner: nil, group: nil, preserve: nil, noop: nil, verbose: nil) Показать исходный код
# File lib/fileutils.rb, line 862
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
      copy_file s, d
      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

Если src не совпадает с dest, копирует его и изменяет права доступа на mode. Если dest — это каталог, то целевой путь — dest/src. Этот метод удаляет целевой файл перед копированием.

FileUtils.install 'ruby', '/usr/local/bin/ruby', mode: 0755, verbose: true
FileUtils.install 'lib.rb', '/usr/local/lib/ruby/site_ruby', verbose: true
link(src, dest, force: nil, noop: nil, verbose: nil)
Псевдоним для: ln
link_entry(src, dest, dereference_root = false, remove_destination = false) Показать исходный код
# File lib/fileutils.rb, line 406
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

Создаёт жёсткую ссылку на системный элемент src в dest. Если src — это каталог, этот метод создаёт ссылки на его содержимое рекурсивно.

Оба значения src и dest должны быть именами путей. src должен существовать, dest — нет.

Если dereference_root равно true, этот метод дескриптирует корень дерева.

Если remove_destination равно true, этот метод удаляет каждый целевой файл перед копированием.

ln(target, link, force: nil, noop: nil, verbose: nil) Показать исходный код
ln(target, dir, force: nil, noop: nil, verbose: nil)
ln(targets, dir, force: nil, noop: nil, verbose: nil)
# File lib/fileutils.rb, line 303
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

В первом варианте создаёт жёсткую ссылку link, которая указывает на target. Если link уже существует, генерируется исключение Errno::EEXIST. Но если опция force установлена, перезаписывает link.

FileUtils.ln 'gcc', 'cc', verbose: true
FileUtils.ln '/usr/bin/emacs21', '/usr/bin/emacs'

Во втором варианте создаёт ссылку dir/target, указывающую на target. В третьем варианте создаёт несколько жёстких ссылок в каталоге dir, указывающих на каждый элемент в targets. Если dir не является каталогом, генерируется исключение Errno::ENOTDIR.

FileUtils.cd '/sbin'
FileUtils.ln %w(cp mv mkdir), '/bin'   # Now /sbin/cp and /bin/cp are linked.
Также алиас: link
ln_s(target, link, force: nil, noop: nil, verbose: nil) Показать исходный код
ln_s(target, dir, force: nil, noop: nil, verbose: nil)
ln_s(targets, dir, force: nil, noop: nil, verbose: nil)
# File lib/fileutils.rb, line 369
def ln_s(src, dest, force: nil, noop: nil, verbose: nil)
  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

В первом варианте создаёт символическую ссылку link, которая указывает на target. Если link уже существует, генерируется исключение Errno::EEXIST. Но если опция force установлена, перезаписывает link.

FileUtils.ln_s '/usr/bin/ruby', '/usr/local/bin/ruby'
FileUtils.ln_s 'verylongsourcefilename.c', 'c', force: true

Во втором варианте создаёт ссылку dir/target, указывающую на target. В третьем варианте создаёт несколько символических ссылок в каталоге dir, указывающих на каждый элемент в targets. Если dir не является каталогом, генерируется исключение Errno::ENOTDIR.

FileUtils.ln_s Dir.glob('/bin/*.rb'), '/home/foo/bin'
Также алиас: symlink
ln_sf(*args) Показать исходный код
# File lib/fileutils.rb, line 390
def ln_sf(src, dest, noop: nil, verbose: nil)
  ln_s src, dest, force: true, noop: noop, verbose: verbose
end

То же, что

FileUtils.ln_s(*args, force: true)
makedirs(list, mode: nil, noop: nil, verbose: nil)
Псевдоним для: mkdir_p
mkdir(list, mode: nil, noop: nil, verbose: nil) Показать исходный код
# File lib/fileutils.rb, line 180
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

Создаёт один или несколько каталогов.

FileUtils.mkdir 'test'
FileUtils.mkdir %w(tmp data)
FileUtils.mkdir 'notexist', noop: true  # Does not really create.
FileUtils.mkdir 'tmp', mode: 0700
mkdir_p(list, mode: nil, noop: nil, verbose: nil) Показать исходный код
# File lib/fileutils.rb, line 206
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.map {|path| remove_trailing_slash(path)}.each do |path|
    # optimize for the most common case
    begin
      fu_mkdir path, mode
      next
    rescue SystemCallError
      next if File.directory?(path)
    end

    stack = []
    until path == stack.last   # dirname("/")=="/", dirname("C:/")=="C:/"
      stack.push path
      path = File.dirname(path)
    end
    stack.pop                 # root directory should exist
    stack.reverse_each do |dir|
      begin
        fu_mkdir dir, mode
      rescue SystemCallError
        raise unless File.directory?(dir)
      end
    end
  end

  return *list
end

Создаёт каталог и все его родительские каталоги. Например,

FileUtils.mkdir_p '/usr/local/lib/ruby'

приводит к созданию следующих каталогов, если они не существуют.

  • /usr

  • /usr/local

  • /usr/local/lib

  • /usr/local/lib/ruby

Вы можете передавать несколько каталогов одновременно в списке.

Также алиас: mkpath, makedirs
mkpath(list, mode: nil, noop: nil, verbose: nil)
Псевдоним для: mkdir_p
move(src, dest, force: nil, noop: nil, verbose: nil, secure: nil)
Псевдоним для: mv
mv(src, dest, force: nil, noop: nil, verbose: nil, secure: nil) Показать исходный код
# File lib/fileutils.rb, line 536
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. Если file и dest находятся на разных разделах диска, файл копируется, а затем исходный файл удаляется.

FileUtils.mv 'badname.rb', 'goodname.rb'
FileUtils.mv 'stuff.rb', '/notexist/lib/ruby', force: true  # no error

FileUtils.mv %w(junk.txt dust.txt), '/home/foo/.trash/'
FileUtils.mv Dir.glob('test*.rb'), 'test', noop: true, verbose: true
Также алиас: move
pwd() Показать исходный код
# File lib/fileutils.rb, line 115
def pwd
  Dir.pwd
end

Возвращает имя текущего каталога.

Также алиас: getwd
remove(list, force: nil, noop: nil, verbose: nil)
Псевдоним для: rm
remove_dir(path, force = false) Показать исходный код
# File lib/fileutils.rb, line 805
def remove_dir(path, force = false)
  remove_entry path, force   # FIXME?? check if it is a directory
end

Удаляет каталог dir и его содержимое рекурсивно. Этот метод игнорирует StandardError, если force равно true.

remove_entry(path, force = false) Показать исходный код
# File lib/fileutils.rb, line 777
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 может быть обычным файлом, каталогом или чем-то ещё. Если path является каталогом, удаляет его рекурсивно.

См. также remove_entry_secure.

remove_entry_secure(path, force = false) Показать исходный код
# File lib/fileutils.rb, line 684
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 должен быть обычным файлом, каталогом или чем-то подобным. Если path является каталогом, он удаляется рекурсивно. Этот метод необходим для предотвращения локальной проблемы безопасности TOCTTOU (time-of-check-to-time-of-use) при использовании rm_r. rm_r создаёт уязвимость, когда:

  • Родительский каталог имеет разрешения для записи всем (включая /tmp).

  • Дерево удаляемых каталогов включает каталог с разрешениями для записи всем.

  • В системе присутствуют символические ссылки.

Чтобы избежать этой уязвимости, этот метод применяет специальную предобработку. Если path является каталогом, этот метод использует chown(2) и chmod(2) для всех удаляемых каталогов. Это требует, чтобы текущий процесс был владельцем всего удаляемого дерева каталогов или являлся суперпользователем (root).

ВНИМАНИЕ: Вы должны убедиться, что ВСЕ родительские каталоги не могут быть изменены другими ненадежными пользователями. Например, родительские каталоги не должны принадлежать ненадежным пользователям и не должны иметь разрешения для записи всем, за исключением случаев, когда установлен бит "sticky".

ВНИМАНИЕ: Этот метод должен вызываться только владельцем удаляемого дерева каталогов или суперпользователем (root) системы. В противном случае метод не будет работать.

Подробная информация об этой уязвимости см. в примере с Perl:

  • cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0448

  • cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452

Для fileutils.rb эта уязвимость была сообщена в [ruby-dev:26100].

remove_file(path, force = false) Показать исходный код
# File lib/fileutils.rb, line 794
def remove_file(path, force = false)
  Entry_.new(path).remove_file
rescue
  raise unless force
end

Удаляет файл path. Этот метод игнорирует StandardError, если force равно true.

rm(list, force: nil, noop: nil, verbose: nil) Показать исходный код
# File lib/fileutils.rb, line 576
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. Этот метод не может удалять каталоги. Все StandardErrors игнорируются, когда установлен параметр :force.

FileUtils.rm %w( junk.txt dust.txt )
FileUtils.rm Dir.glob('*.so')
FileUtils.rm 'NotExistFile', force: true   # never raises exception
Также алиас: remove
rm_f(list, noop: nil, verbose: nil) Показать исходный код
# File lib/fileutils.rb, line 595
def rm_f(list, noop: nil, verbose: nil)
  rm list, force: true, noop: noop, verbose: verbose
end

Эквивалентно

FileUtils.rm(list, force: true)
Также алиас: safe_unlink
rm_r(list, force: nil, noop: nil, verbose: nil, secure: nil) Показать исходный код
# File lib/fileutils.rb, line 622
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[0] list[1]… Если list[n] является каталогом, удаляет все его содержимое рекурсивно. Этот метод игнорирует StandardError при установленном параметре :force.

FileUtils.rm_r Dir.glob('/tmp/*')
FileUtils.rm_r 'some_dir', force: true

ВНИМАНИЕ: Этот метод может привести к локальной уязвимости, если один из родительских каталогов или удаляемое дерево каталогов имеют разрешения для записи всем (включая /tmp, чьи разрешения 1777), и текущий процесс имеет сильные привилегии, такие как суперпользователь (root), и в системе присутствуют символические ссылки. Для безопасного удаления внимательно прочитайте документацию remove_entry_secure, и установите параметр :secure в значение true. Значение по умолчанию - secure: false.

ПРИМЕЧАНИЕ: Этот метод вызывает remove_entry_secure, если установлен параметр :secure. См. также remove_entry_secure.

rm_rf(list, noop: nil, verbose: nil, secure: nil) Показать исходный код
# File lib/fileutils.rb, line 644
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)

ВНИМАНИЕ: Этот метод может привести к локальной уязвимости. Сначала прочитайте документацию rm_r.

Также алиас: rmtree
rmdir(list, parents: nil, noop: nil, verbose: nil) Показать исходный код
# File lib/fileutils.rb, line 263
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

Удаляет один или несколько каталогов.

FileUtils.rmdir 'somedir'
FileUtils.rmdir %w(somedir anydir otherdir)
# Does not really remove directory; outputs message.
FileUtils.rmdir 'somedir', verbose: true, noop: true
rmtree(list, noop: nil, verbose: nil, secure: nil)
Псевдоним для: rm_rf
safe_unlink(list, noop: nil, verbose: nil)
Псевдоним для: rm_f
symlink(src, dest, force: nil, noop: nil, verbose: nil)
Псевдоним для: ln_s
touch(list, noop: nil, verbose: nil, mtime: nil, nocreate: nil) Показать исходный код
# File lib/fileutils.rb, line 1137
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. Файлы создаются, если они не существуют.

FileUtils.touch 'timestamp'
FileUtils.touch Dir.glob('*.c');  system 'make'
uptodate?(new, old_list) Показать исходный код
# File lib/fileutils.rb, line 155
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. Несуществующие файлы считаются старее любого файла.

FileUtils.uptodate?('hello.o', %w(hello.c hello.h)) or \
    system 'make hello.o'

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

Spec-Zone.ru

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